2

C code:

#include <stdio.h>

main() {
    int i;
    for (i = 0; i < 10; i++) {
        printf("%s\n", "hello");
    }
}

ASM:

    .file   "simple_loop.c"
    .section    .rodata
.LC0:
    .string "hello"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushl   %ebp # push ebp onto stack
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp # setup base pointer or stack ?
    .cfi_def_cfa_register 5
    andl    $-16, %esp # ? 
    subl    $32, %esp # ?
    movl    $0, 28(%esp) # i = 0
    jmp .L2
.L3:
    movl    $.LC0, (%esp) # point stack pointer to "hello" ?
    call    puts # print "hello"
    addl    $1, 28(%esp) # i++
.L2:
    cmpl    $9, 28(%esp) # if i < 9
    jle .L3              # goto l3
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret

So I am trying to improve my understanding of x86 assembly code. For the above code, I marked off what I believe I understand. As for the question marked content, could someone share some light? Also, if any of my comments are off, please let me know.

2
  • My assembly knowledge is limited to MIPS rather than x86 so I can't really help with saying whether you are right so far or not. I can however give you the link to the book I plan on going through at some point to learn x86 assembly. It's all in a PDF here: http://www.planetpdf.com/codecuts/pdfs/aoa.pdf Commented Mar 11, 2012 at 0:01
  • 1
    What are your doubts exactly? Commented Mar 11, 2012 at 0:07

1 Answer 1

2
andl    $-16, %esp # ? 
subl    $32, %esp # ?

This reserves some space on the stack. First, the andl instruction rounds the %esp register down to the next lowest multiple of 16 bytes (exercise: find out what the binary value of -16 is to see why). Then, the subl instruction moves the stack pointer down a bit further (32 bytes), reserving some more space (which it will use next). I suspect this rounding is done so that access through the %esp register is slightly more efficient (but you'd have to inspect your processor data sheets to figure out why).

movl    $.LC0, (%esp) # point stack pointer to "hello" ?

This places the address of the string "hello" onto the stack (this instruction doesn't change the value of the %esp register itself). Apparently your compiler considers it more efficient to move data onto the stack directly, rather than to use the push instruction.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.