Understanding x86 assembly code from C code

C code:

#include <stdio.h>

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



    .file   "simple_loop.c"
    .section    .rodata
    .string "hello"
    .globl  main
    .type   main, @function
    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
    movl    $.LC0, (%esp) # point stack pointer to "hello" ?
    call    puts # print "hello"
    addl    $1, 28(%esp) # i++
    cmpl    $9, 28(%esp) # if i < 9
    jle .L3              # goto l3
    .cfi_restore 5
    .cfi_def_cfa 4, 4


So, I am trying to improve my understanding of x86 assembly code. In the above code, I noted that as I understand it, I understand it. As for the content question, can anyone share some light? Also, if any of my comments are off, please let me know.


source to share

1 answer

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


This reserves some space on the stack. First, the instruction andl

rounds the register %esp

to the next lowest multiple of 16 bytes (Exercise: Learn the binary value -16

should figure out why). The command then subl

moves the stack pointer a bit (32 bytes), saving some more space (which it will use later). I suspect this rounding is done to make register access a %esp

little more efficient (but you will need to check your processor datasheets to figure out why).

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


This pushes the address of the string "hello"

onto the stack (this instruction does not change the value of the register itself %esp

). Obviously, your compiler considers it more efficient to push data onto the stack directly rather than using an instruction push




All Articles