3

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.

Sep Roland
  • 33,889
  • 7
  • 43
  • 76
roirodriguez
  • 1,685
  • 2
  • 17
  • 31
  • 4
    `test` doesn't do what you think. You want a `cmp`. Also, you want `je` not `jne`. The syscall number for `exit` is 1 not 0. – Jester Sep 02 '17 at 14:29
  • Ok, this works. Seems that i need to read better sources. If you're interested on posting an answer with any good reference for jumps and cmp i'll be pleased to mark it as correct... – roirodriguez Sep 02 '17 at 15:09
  • 1
    usually google search like "x86 instruction test" will lead to one of the HTML versions of instruction reference guide, like [http://x86.renejeschke.de/](http://x86.renejeschke.de/) and similar. Sometimes they contain tiny inaccuracies, but usually they are the first thing to check (together with debugger) if something is not working as expected. Only when debugger proves those shortened versions wrong, it's time to dig into official Intel docs (freely available pdf on Intel web), or cross-check several of the quick references. For programming in ASM it's essential to use both: debugger + docs – Ped7g Sep 03 '17 at 16:11

1 Answers1

2

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
Johan
  • 74,508
  • 24
  • 191
  • 319