roirodriguez
roirodriguez

Reputation: 1740

Conditional jump not taken

I'm beginning with assembly (x86, linux), just for fun. This is my very first little program, which just checks if I passed one argument through command line and if not it prints a message, and it exits after that:

section .text
    global  _start

_start: 
    pop ebx     ;argc
    dec ebx
    test    ebx,1
    jne print_string
exit:
    mov ebx,0
    mov eax,0
    int 0x80

print_string:
    mov edx,len
    mov ecx,msg
    mov ebx,1
    mov eax,4
    int 0x80
    call    exit

section .data
msg db  "Ok, no arg was passed",0xa
len equ $ - msg

I'm having two problems with the code above:

  1. jne is not taken. I checked with gdb that ebx is equal to 0x00 after dec, but EFLAGS are not changed by the test instruction.
  2. exit syscall does not exit! So instead of exiting I just got my message printed in an infinite loop, as print_string is calling exit and after exit there goes print_string over and over again.

What's happening here? Also any other recommendations about the code will be welcome. Thanks.

Upvotes: 3

Views: 548

Answers (1)

Johan
Johan

Reputation: 76537

The test instruction performs a bitwise and without altering the register operands.
test ebx,1 performs: flags = (ebx and 1). Or ZF = IsEven(ebx).

If you want to test whether ebx = 1 you need to use a cmp.
cmp performs a subtract without altering the register operands.

cmp ebx,1 performs flags = ebx - 1 Or ZF = (ebx = 1).

syscall exit
You've got the wrong parameters for exit().

the correct code is:

exit:
    mov ebx,0
    mov eax,1    <<-- 
    int 0x80

Upvotes: 2

Related Questions