global _start
section .text
;
; [ebp+8] is pointer to string
; [ebp+12] is pointer to pattern
; returns eax==0 for false, eax==1 for true
;
match:
push ebp
mov ebp, esp
sub esp, 4 ; local I (index) is [ebp-4]
push esi ; we use esi, edi and eax,
push edi ; but eax is changed anyway
mov esi, [ebp+8] ; esi always points to the string
mov edi, [ebp+12] ; edi -------------------- pattern
.again:
cmp byte [edi], 0 ; pattern end?
jne .not_end
cmp byte [esi], 0 ; string end?
jne near .false ; out of range
jmp .true
.not_end:
cmp byte [edi], '*'
jne .not_star
; now the "star cycle" begins
mov dword [ebp-4], 0 ; I := 0
.star_loop:
; prepare the recursive call
mov eax, edi ; second arg of match is pattern+1
inc eax
push eax
mov eax, esi ; first arg of match is string+I
add eax, [ebp-4] ; prepare the recursive call
push eax
call match
add esp, 8 ; remove params from stack
test eax, eax ; what is returned, true or false?
jnz .true ; if 1, then match is found, return 1
add eax, [ebp-4]
cmp byte [esi+eax], 0 ; may be string ended?
je .false ; if so, no more possibilities to try
inc dword [ebp-4] ; I := I + 1
jmp .star_loop ; try the next possibility
.not_star:
mov al, [edi] ; we already know pattern isn't ended
cmp al, '?'
je .quest
cmp al, [esi] ; if the string's over, this cmp fails
jne .false ; as well as if the chars differ
jmp .goon
.quest:
cmp byte [esi], 0 ; we only need to check for string end
jz .false
.goon:
inc esi
inc edi
jmp .again
.true:
mov eax, 1
jmp .quit
.false:
xor eax, eax
.quit:
pop edi
pop esi
mov esp, ebp
pop ebp
ret
;
; MAIN PROGRAM
;
_start:
pop eax
cmp eax, 3
jne wrong_args
pop esi ; ignore argv[0]
pop esi ; get argv[1]
pop edi ; get argv[2]
mov [string], esi
mov [pattern], edi
push edi
push esi
call match
add esp, 8
test eax, eax
jz print_no
mov edx, 4 ; print yes
mov ecx, m_yes
mov ebx, 1
mov eax, 4
int 80h
jmp quit
print_no: ; print no
mov edx, 4
mov ecx, m_no
mov ebx, 1
mov eax, 4
int 80h
jmp quit
wrong_args: ; say wrong args
mov edx, m_wrong_len
mov ecx, m_wrong
mov ebx, 1
mov eax, 4
int 80h
jmp quit
quit:
mov ebx, 0
mov eax, 1
int 80h
section .bss
string resd 1
pattern resd 1
section .data
m_yes db "YES", 10
m_no db "NO ", 10
m_wrong db "wrong arguments count, must be 2", 10
m_wrong_len equ $-m_wrong
Z2xvYmFsIF9zdGFydAoKc2VjdGlvbiAudGV4dAoKOwo7ICBbZWJwKzhdIGlzIHBvaW50ZXIgdG8gc3RyaW5nCjsgIFtlYnArMTJdIGlzIHBvaW50ZXIgdG8gcGF0dGVybgo7ICByZXR1cm5zIGVheD09MCBmb3IgZmFsc2UsIGVheD09MSBmb3IgdHJ1ZQo7Cm1hdGNoOgoJCXB1c2ggZWJwCgkJbW92IGVicCwgZXNwCgkJc3ViIGVzcCwgNAkJOyBsb2NhbCBJIChpbmRleCkgaXMgW2VicC00XQoJCXB1c2ggZXNpCQk7IHdlIHVzZSBlc2ksIGVkaSAgYW5kIGVheCwKCQlwdXNoIGVkaQkJOyBidXQgZWF4IGlzIGNoYW5nZWQgYW55d2F5CgkJbW92IGVzaSwgW2VicCs4XQk7IGVzaSBhbHdheXMgcG9pbnRzIHRvIHRoZSBzdHJpbmcKCQltb3YgZWRpLCBbZWJwKzEyXQk7IGVkaSAtLS0tLS0tLS0tLS0tLS0tLS0tLSBwYXR0ZXJuCi5hZ2FpbjoKCQljbXAgYnl0ZSBbZWRpXSwgMAk7IHBhdHRlcm4gZW5kPwoJCWpuZSAubm90X2VuZAoJCWNtcCBieXRlIFtlc2ldLCAwCTsgc3RyaW5nIGVuZD8KCQlqbmUgbmVhciAuZmFsc2UJCTsgb3V0IG9mIHJhbmdlCgkJam1wIC50cnVlCi5ub3RfZW5kOgoJCWNtcCBieXRlIFtlZGldLCAnKicKCQlqbmUgLm5vdF9zdGFyCgkJCQkJOyBub3cgdGhlICJzdGFyIGN5Y2xlIiBiZWdpbnMKCQltb3YgZHdvcmQgW2VicC00XSwgMAk7IEkgOj0gMAouc3Rhcl9sb29wOgoJCQkJCTsgcHJlcGFyZSB0aGUgcmVjdXJzaXZlIGNhbGwKCQltb3YgZWF4LCBlZGkJCTsgc2Vjb25kIGFyZyBvZiBtYXRjaCBpcyBwYXR0ZXJuKzEKCQlpbmMgZWF4CgkJcHVzaCBlYXgKCQltb3YgZWF4LCBlc2kJCTsgZmlyc3QgYXJnIG9mIG1hdGNoIGlzIHN0cmluZytJCgkJYWRkIGVheCwgW2VicC00XQk7IHByZXBhcmUgdGhlIHJlY3Vyc2l2ZSBjYWxsCgkJcHVzaCBlYXgKCQljYWxsIG1hdGNoCgkJYWRkIGVzcCwgOAkJOyByZW1vdmUgcGFyYW1zIGZyb20gc3RhY2sKCQl0ZXN0IGVheCwgZWF4CQk7IHdoYXQgaXMgcmV0dXJuZWQsIHRydWUgb3IgZmFsc2U/CgkJam56IC50cnVlCQk7IGlmIDEsIHRoZW4gbWF0Y2ggaXMgZm91bmQsIHJldHVybiAxCgkJYWRkIGVheCwgW2VicC00XQoJCWNtcCBieXRlIFtlc2krZWF4XSwgMAk7IG1heSBiZSBzdHJpbmcgZW5kZWQ/CgkJamUgLmZhbHNlCQk7IGlmIHNvLCBubyBtb3JlIHBvc3NpYmlsaXRpZXMgdG8gdHJ5CgkJaW5jIGR3b3JkIFtlYnAtNF0JOyBJIDo9IEkgKyAxCgkJam1wIC5zdGFyX2xvb3AJCTsgdHJ5IHRoZSBuZXh0IHBvc3NpYmlsaXR5Ci5ub3Rfc3RhcjoKCQltb3YgYWwsIFtlZGldCQk7IHdlIGFscmVhZHkga25vdyBwYXR0ZXJuIGlzbid0IGVuZGVkCgkJY21wIGFsLCAnPycKCQlqZSAucXVlc3QKCQljbXAgYWwsIFtlc2ldCQk7IGlmIHRoZSBzdHJpbmcncyBvdmVyLCB0aGlzIGNtcCBmYWlscwoJCWpuZSAuZmFsc2UJCTsgYXMgd2VsbCBhcyBpZiB0aGUgY2hhcnMgZGlmZmVyCgkJam1wIC5nb29uCi5xdWVzdDoKCQljbXAgYnl0ZSBbZXNpXSwgMAk7IHdlIG9ubHkgbmVlZCB0byBjaGVjayBmb3Igc3RyaW5nIGVuZAoJCWp6IC5mYWxzZQouZ29vbjoKCQlpbmMgZXNpCgkJaW5jIGVkaQoJCWptcCAuYWdhaW4KLnRydWU6CgkJbW92IGVheCwgMQoJCWptcCAucXVpdAouZmFsc2U6CgkJeG9yIGVheCwgZWF4Ci5xdWl0OgoJCXBvcCBlZGkKCQlwb3AgZXNpCgkJbW92IGVzcCwgZWJwCgkJcG9wIGVicAoJCXJldAoKCgo7CjsgIE1BSU4gUFJPR1JBTQo7Cl9zdGFydDoKCQlwb3AgZWF4CgkJY21wIGVheCwgMwoJCWpuZSB3cm9uZ19hcmdzCgkJcG9wIGVzaSAgOyBpZ25vcmUgYXJndlswXQoJCXBvcCBlc2kgIDsgZ2V0IGFyZ3ZbMV0KCQlwb3AgZWRpICA7IGdldCBhcmd2WzJdCgkJbW92IFtzdHJpbmddLCBlc2kKCQltb3YgW3BhdHRlcm5dLCBlZGkKCgkJcHVzaCBlZGkKCQlwdXNoIGVzaQoJCWNhbGwgbWF0Y2gKCQlhZGQgZXNwLCA4CgkJdGVzdCBlYXgsIGVheAoJCWp6IHByaW50X25vCgoJCW1vdiBlZHgsIDQJCTsgcHJpbnQgeWVzCgkJbW92IGVjeCwgbV95ZXMKCQltb3YgZWJ4LCAxCgkJbW92IGVheCwgNAoJCWludCA4MGgKCQlqbXAgcXVpdApwcmludF9ubzoJCQk7IHByaW50IG5vCgkJbW92IGVkeCwgNAoJCW1vdiBlY3gsIG1fbm8KCQltb3YgZWJ4LCAxCgkJbW92IGVheCwgNAoJCWludCA4MGgKCQlqbXAgcXVpdAoKd3JvbmdfYXJnczoJCQk7IHNheSB3cm9uZyBhcmdzCgkJbW92IGVkeCwgbV93cm9uZ19sZW4KCQltb3YgZWN4LCBtX3dyb25nCgkJbW92IGVieCwgMQoJCW1vdiBlYXgsIDQKCQlpbnQgODBoCgkJam1wIHF1aXQKCgpxdWl0OgoJCW1vdiBlYngsIDAKCQltb3YgZWF4LCAxCgkJaW50IDgwaAkKCnNlY3Rpb24gLmJzcwoKc3RyaW5nCQlyZXNkCTEKcGF0dGVybgkJcmVzZAkxCgpzZWN0aW9uIC5kYXRhCgptX3llcwkJZGIJIllFUyIsIDEwCm1fbm8JCWRiCSJOTyAiLCAxMAptX3dyb25nCQlkYgkid3JvbmcgYXJndW1lbnRzIGNvdW50LCBtdXN0IGJlIDIiLCAxMAptX3dyb25nX2xlbgllcXUJJC1tX3dyb25nCg==