2012-03-10 3 views
3

Cコード:理解のx86アセンブリコード

#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アセンブリコードの私の理解を改善しようとしています。上記のコードでは、私が理解していると思ったものをマークしました。質問の内容は誰かが光を分かち合うことができますか?また、私のコメントのいずれかがオフの場合、私に知らせてください。

+1

あなたの疑問は何ですか? – Saphrosit

+0

私のアセンブリに関する知識は、x86ではなくMIPSに限られているので、あなたが今のところ正しいのかどうかということを本当に助けることはできません。しかし、私はあなたに、ある時点でx86アセンブリを学ぶ予定の本へのリンクを与えることができます。それはすべてここにPDFの:[http://www.planetpdf.com/codecuts/pdfs/aoa.pdf] (http://www.planetpdf.com/codecuts/pdfs/aoa.pdf) –

答えて

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

これは、スタックにスペースを確保します。まず、andl命令は、%espレジスタを16バイトの次の最も小さい倍数に丸めます(練習:なぜ-16のバイナリ値が何であるか調べてください)。次に、subl命令はスタックポインタをさらにビット(32バイト)下に移動し、さらにスペースを確保します(次に使用する)。私はこの丸めが行われて、%espレジスタ経由のアクセスがやや効率的だと考えています(しかし、理由を理解するためにプロセッサのデータシートを調べなければなりません)。

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

これは(この命令は、自身を登録%espの値を変更しません)スタック上に文字列"hello"アドレスを配置します。コンパイラは、push命令を使用するのではなく、スタックに直接データを移動する方が効率的だと考えているようです。

+0

優れています。それは理にかなっている。 –

関連する問題