Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incrementing from 0 to 100 in assembly language

This is kinda oddball, but I was poking around with the GNU assembler today (I want to be able to at least read the syntax), and was trying to get this little contrived example of mine to work. Namely I just want to go from 0 to 100, printing out numbers all the while. So a few minutes later I come up with this:

# count.s: print the numbers from 0 to 100. 
    .text
string: .asciz "%d\n"
    .globl _main

_main:
    movl    $0, %eax # The starting point/current value.
    movl    $100,   %ebx # The ending point.

_loop:
    # Display the current value.
    pushl   %eax
    pushl   $string
    call     _printf
    addl     $8, %esp

    # Check against the ending value.
    cmpl    %eax, %ebx
    je    _end

    # Increment the current value.
    incl    %eax
    jmp _loop   

_end:

All I get from this is 3 printed over and over again. Like I said, just a little contrived example, so don't worry too much about it, it's not a life or death problem.

(The formatting's a little messed up, but nothing major).

like image 222
Bernard Avatar asked Aug 21 '08 06:08

Bernard


People also ask

What does LC0 mean in assembly?

LC0 , which is the address of the constant string in the rodata section). Then we call printf() . addl $20, %esp. When printf() returns, we remove the space allocated for the arguments. This addl cancels what the subl above did.

What is %d assembly?

Instead of assembling a machine code instruction, it dumps raw bytes into the code stream (. data section in this case). "%d", 10, 0 are the bytes to dump into the stream. The first is an ascii string, which dumps two bytes (the characters '%' and 'd'), 10 is a newline character ( \n in C), and 0 is a null byte.

What does 0 mean in assembly?

%0 is just the first input/output operand defined in your code. In practice, this could be a stack variable, a heap variable or a register depending on how the assembly code generated by the compiler.


2 Answers

You can't trust what any called procedure does to any of the registers. Either push the registers onto the stack and pop them back off after calling printf or have the increment and end point values held in memory and read/written into registers as you need them.

I hope the following works. I'm assuming that pushl has an equivalant popl and you can push an extra couple of numbers onto the stack.

# count.s: print the numbers from 0 to 100. 
    .text
string: .asciz "%d\n"
    .globl _main

_main:
    movl    $0, %eax # The starting point/current value.
    movl    $100,       %ebx # The ending point.

_loop:
    # Remember your registers.
    pushl   %eax
    pushl   %ebx

    # Display the current value.
    pushl   %eax
    pushl   $string
    call     _printf
    addl     $8, %esp

    # reinstate registers.
    popl   %ebx
    popl   %eax

    # Check against the ending value.
    cmpl    %eax, %ebx
    je    _end

    # Increment the current value.
    incl    %eax
    jmp _loop   

_end:
like image 165
seanyboy Avatar answered Sep 19 '22 23:09

seanyboy


I'm not too familiar with _printf, but could it be that it modifies eax? Printf should return the number of chars printed, which in this case is two: '0' and '\n'. I think it returns this in eax, and when you increment it, you get 3, which is what you proceed to print. You might be better off using a different register for the counter.

like image 24
Nathan Fellman Avatar answered Sep 18 '22 23:09

Nathan Fellman