format ELF executable
sys_exit equ 1
sys_read equ 3
sys_write equ 4
stdin equ 0
stdout equ 1
stderr equ 2
entry _start
segment executable
; --- linux specific ---
; _noreturn program_end()
program_end:
mov eax, sys_exit
xor ebx, ebx
int 80h
; void print(char *s)
; s should be on the stack
print:
push ebp
mov ebp, esp
push esi
mov esi, [ebp+8]
call strlen
mov edx, eax
mov ecx, esi
mov ebx, stdout
mov eax, sys_write
int 80h
pop esi
leave
ret
; --- platform independent ---
; int strlen(char *s)
; s should be in esi
; returns the strings length in eax
strlen:
push edi
mov edi, esi
xor al, al
mov ecx, -1
repne scasb
inc ecx
neg ecx
mov eax, ecx
pop edi
ret
; int strchr(char *s, char x)
; s should be in esi, x in dl
; returns position of first occurence of x
; in s (or -1 if there is none)
strchr:
push esi
test dl, dl
jz .notfound
xor ecx, ecx
@@:
lodsb
test al, al
jz .notfound
inc ecx
cmp al, dl
je .exit
jmp @b
.notfound:
xor ecx, ecx
.exit:
mov eax, ecx
dec eax
pop esi
ret
; int strcmp(char *s1, char *s2)
; s1 in esi, s2 in edi
; returns 0 if the strings are equal
; nonzero otherwise
stricmp:
push esi
push edi
xor eax, eax
@@:
mov al, [esi]
mov ah, [edi]
inc esi
inc edi
cmp al, 'a'
jb .alok
cmp al, 'z'
ja .alok
and al, not 32
.alok:
cmp ah, 'a'
jb .ahok
cmp ah, 'z'
ja .ahok
and ah, not 32
.ahok:
cmp al, ah
jne .notequal
test al, al
jz .equal
jmp @b
.equal:
xor eax, eax
jmp .exit
.notequal:
mov al, 1
.exit:
pop edi
pop esi
ret
; tld_verify(char *tld)
; tld should be in esi
; returns 0 in eax if tld is valid
; and non-zero otherwise
tld_verify:
push esi
mov ecx, [tld_count]
@@:
mov edi, [tld_list+ecx*4-4]
push ecx
call stricmp
pop ecx
test eax, eax
jz .oktld
loop @b
mov al, 1
jmp .exit
.oktld:
xor eax, eax
.exit:
pop esi
ret
; email_verify(char *s)
; s should be in esi
; returns 0 in eax if e-mail address is syntactically correct
; and non-zero otherwise
email_verify:
push ebp
mov ebp, esp
sub esp, 24
xor ecx, ecx ; total length count
mov [ebp-4], esi
mov [ebp-8], edi
mov [ebp-16], ecx ; <-- save last character
mov [ebp-24], ecx ; <-- store tld
.localpart:
lodsb
test al, al
jz .incorrect
cmp al, '@'
je .localpart_exit
cmp ecx, 64
jge .incorrect
cmp al, '.'
jne .localpart_nodot
test ecx, ecx
jz .incorrect ; no dot as first character
xchg eax,[ebp-16]
cmp al, '.'
je .incorrect ; dot may not follow dot
jmp .localpart
.localpart_nodot:
inc ecx
mov [ebp-12], ecx
mov [ebp-16], eax
mov edi, esi
mov dl, al
mov esi, localpart_chars
call strchr
mov esi, edi
mov ecx, [ebp-12]
test eax, eax
js .incorrect
; character was ok
jmp .localpart
.localpart_exit:
cmp ecx, 64 ; local part maximum length is 64 characters
jg .incorrect
mov eax, [ebp-16]
cmp al, '.'
je .incorrect ; dot cannot be last character in local part
inc ecx
xor edx, edx
.domainpart:
lodsb
test al, al
jz .domainpart_exit
cmp edx, 64
jge .incorrect
cmp al, '-'
jne .domainpart_nohyphen
test edx, edx
jz .incorrect ; hyphen may not start a domain segment
.domainpart_nohyphen:
cmp al, '.'
jne .domainpart_nodot
test edx, edx
jz .incorrect ; no dot as first character
xchg eax, [ebp-16]
cmp al, '-' ; hyphen may not end a domain segment
je .incorrect
mov [ebp-24], esi
xor edx, edx
jmp .domainpart
.domainpart_nodot:
inc ecx
inc edx
mov [ebp-12], ecx
mov [ebp-16], eax
mov [ebp-20], edx
mov edi, esi
mov dl, al
mov esi, domainpart_chars
call strchr
mov esi, edi
mov ecx, [ebp-12]
mov edx, [ebp-20]
test eax, eax
js .incorrect
jmp .domainpart
.domainpart_exit:
test edx, edx
jz .incorrect
cmp ecx, 256
jg .incorrect
mov esi, [ebp-24]
test esi, esi
jz @f ; <- no tld
call tld_verify
test eax, eax
jnz .incorrect ; <- invalid tld
@@:
.correct:
xor eax, eax
jmp .exit
.incorrect:
mov eax, 1
.exit:
mov edi, [ebp-8]
mov esi, [ebp-4]
leave
ret
; program entry point
_start:
nop
push ebp
mov ebp, esp
cmp dword [ebp+4], 2
je .args_correct
; incorrect number of arguments
push cmd_args_s
call print
add esp, 4
jmp .exit
.args_correct:
mov esi, [ebp+12]
call email_verify
test eax, eax
jnz .verify_error
; verify correct
push email_ok_s
jmp .showstr
.verify_error:
push email_mal_s
.showstr:
call print
add esp,4
.exit:
leave
jmp program_end
segment readable
cmd_args_s db 'call with exactly one argument!',10,0
email_ok_s db 'e-mail address syntax is correct!',10,0
email_mal_s db 'malformed e-mail address!',10,0
localpart_chars:
db "!#$%&'*+/=?^_`{|}~;"
domainpart_chars:
db "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-",0
include 'tlds.asm'