从C代码理解x86汇编代码

3

C代码:

#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

我正在努力提高对x86汇编代码的理解。对于上面的代码,我标记了我相信自己理解的部分。至于标记为问题的内容,有人能给予一些启示吗?如果我评论中有任何错误,请告诉我。


我的汇编知识仅限于MIPS而不是x86,所以我无法帮助你判断你目前是否正确。但是,我可以给你一个链接,这是我计划在某个时候学习x86汇编的书。它全部都在PDF文件中,链接如下:http://www.planetpdf.com/codecuts/pdfs/aoa.pdf - Dale Myers
1
你确切的疑问是什么? - Manlio
1个回答

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

这个操作在栈中保留了一些空间。首先,andl指令将%esp寄存器下舍入到16字节的最低倍数(练习:找出二进制值为-16的原因)。然后,subl指令将堆栈指针向下移动一点(32字节),保留一些更多的空间(下一步将使用它)。我怀疑这种舍入是为了通过%esp寄存器访问稍微更有效率(但您必须检查处理器数据表以找出原因)。

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

这将字符串"hello"地址放入堆栈中(此指令不会更改%esp寄存器的值)。显然,您的编译器认为直接将数据移动到堆栈上比使用push指令更有效率。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接