JohnSmith
JohnSmith

Reputation: 63

NASM assembly jump if equal function

I am very new to assembly programming and just writing small easy programs and doing lots of tutorials to try and teach myself. I spend most of my day using bash and python but assembly has a big advantage in my area of work plus I am fascinated by it to no end.

I am writing a small program to take user input of 'y' or 'n' compare it and output one of 2 messages. Its pretty straight forward however I am unable to figure out where my jump logic is failing and was wondering if anyone could point me in the right direction.

I am using NASM in windows 7 x64, this code compiles without an issue and I have traced the issue back to my jump instructions. Below is my code. My problem is that after entering y or n it does not seem to be calling yes_msg or no_msg properly and after an afternoon on google and on here I've been unable to figure it out. If anyone could help I'd be very grateful.

Thanks.

;compile with nasm.exe -f elf tutorial4.asm
;gcc -m32 tutorial4.o -o tutorial4.exe


global _main
extern _printf
extern _scanf
global _yes_msg
global _no_msg


section .data
msg db "Please say yes or no? [y/n] ", 0
msgy db "You said yes! ", 0
msgn db "You said no! ", 0
yes db 'y', 0
no db 'n', 0
fmt db "%s", 0          


section .bss            
inpt resb 200           


section .text           

_yes_msg: 
    push msgy
    call _printf
    add esp, 4

_no_msg: 
    push msgn
    call _printf
    add esp, 4

_main:
    push ebp
    mov ebp, esp        

    push msg            
    call _printf        
    add esp, 4          

    push inpt           
    push fmt
    call _scanf         
    mov eax, inpt
    mov edx, 'y'
    cmp eax, edx
    jne _no_msg
    jmp _yes_msg
    add esp, 8          

    mov esp, ebp 
    pop ebp
ret

Upvotes: 2

Views: 2052

Answers (2)

Netch
Netch

Reputation: 4562

First, scanf returns number of processed entries (it will reside in eax). Check it, 0 means scanf rejected to parse (and you can't check the buffer because it could keep some garbage - according to NASM documentation, resb provides uninitialized storage, which can be filled, for example, with runtime loader temporary values). You should rely on buffer contents only if scanf returned 1.

Second, your comparing deals with 4-byte values in eax and edx. Again, even if mov edx,'y' fills it with 0x00000075, you can't be sure eax contains only the lowest significant byte. Call cmp al, dl instead.

(BTW, your _yes_msg, _no_msg miss returning to main, and it will print "You said yes!" and then "You said no!" on 'y'. Is it intentional?)

Upvotes: 1

Fifoernik
Fifoernik

Reputation: 9899

Your instruction mov eax, inpt moves the address of the buffer at inpt in the EAX register. You need the first byte at this location, so you have to write mov al, [inpt]. Remember this is NASM!

Now you can compare the contents:

mov dl, 'y'
cmp al, dl

You placed the clean-up for your call to _scanf below an absolute jump and thus it will never be executed. Move it up to just under the call itself:

call _scanf
add esp, 8
mov al, [inpt]

As @Netch said you should probably change the codes at _yes_msg and _no_msg because now you get both messages in a row and additionally don't exit the program like it should.

Upvotes: 1

Related Questions