2015-11-03 92 views
0

我可以編譯它,但是當我運行它時,我得到「分段錯誤」。
如果有人解釋爲什麼會愛。x86彙編分段錯誤

.section .data 
digitformatstr: 
.string "%d\n" 

.section .text 
.global main 

main: 
    push $1337 
    pop  %eax 
    movl %eax, -4(%ebp) 
    push -4(%ebp) 
    push $digitformatstr 
    call printf 
    addl $8, %esp 
+1

使用了'ebp'作爲指針,但我沒有看到你初始化'ebp'指向任何地方的有效地址。 – Michael

+0

我該怎麼做? :/我感到困惑 –

+0

@FelixRabe你想''ebp'指向什麼? – fuz

回答

2

您似乎在使用GNU彙編器和GCC的C庫來構建您的可執行文件。你的代碼的主要問題是你在使用它之前沒有設置寄存器%ebp。通常使用C您的函數首先設置本地堆棧幀,其中包括初始化%ebp。要正確設置本地棧幀,並清理恢復,你可以使用這樣的代碼之前堆棧:

.section .data 
digitformatstr: 
.string "%d\n" 

.section .text 
.global main 

main: 
    push %ebp   /* setup local stack frame */ 
    mov  %esp, %ebp 

    push $1337 
    pop  %eax 
    movl %eax, -4(%ebp) 
    push -4(%ebp) 
    push $digitformatstr 
    call printf 
    addl $8, %esp 

    leave     /* remove local stack frame */ 
    ret 

的入門指南,以堆棧幀和32位C調用約定可以發現here

有關您的代碼的其他評論。你這樣做:

push $1337 
    pop  %eax 
    movl %eax, -4(%ebp) 
    push -4(%ebp) 
    push $digitformatstr 
    call printf 

我不知道你用這段代碼試圖做什麼。它幾乎看起來是你試圖把1337作爲一個局部變量放在堆棧上(但是沒有在堆棧中爲局部變量分配空間)。由於看起來你只是簡單地調用printf,其中第二個參數是一個整數,所以你應該把這個值(1337)放在堆棧上。上面所有的代碼應該簡單地:

push $1337    /* 2nd argument to printf */ 
    push $digitformatstr  /* 1st argument to printf */ 
    call printf    /* call printf 

main最終的清理代碼可能像看起來是:

main: 
    push %ebp   /* setup local stack frame */ 
    mov  %esp, %ebp 

    push $1337   /* 2nd argument to printf */ 
    push $digitformatstr /* 1st argument to printf */ 
    call printf   /* call printf 
    addl $8, %esp  /* cleanup the 2 32 bit arguments */ 
          /* we pushed on the stack */ 

    leave     /* remove local stack frame */ 
    ret 
+0

工作很不錯!代碼完成後,我得到分段錯誤:o它正確打印和所有內容。 –

+0

在底部添加了呼叫退出,現在它似乎工作,Thx再次:)! –

+0

上面的代碼應該使用'leave'和'ret',而不使用'exit'的調用,除非您以某種方式構建與我預期不同的程序。如果你添加到你的問題中,你用來編譯和鏈接的命令可能會給你一個更好的答案。 –