2016-07-16 51 views
-1

嘗試運行GDB並在C主程序進入主函數後繼續發生分段錯誤。C/Assembly子程序分段錯誤

GDB錯誤:

Breakpoint 1, main() at binom_main.c:7 
7 n=10; 
(gdb) s 
10 0; 
(gdb) s 
12 +){ 
(gdb) s 

Program received signal SIGSEGV, Segmentation fault. 
0x00000000004005c4 in otherwise() 
(gdb) 

我編譯的代碼這樣:

as binom.s -o binom.o 
gcc -S -Og binom_main.c 
gcc -c binom_main.s  
gcc binom_main.o binom.o -o runtimes 

我想學習如何使用GDB更有效率些,但像這樣的段錯誤是相當含糊和限制。爲什麼這個段錯誤是在函數開始的時候引起的?我有錯誤地鏈接了兩個文件嗎?

主營:

#include <stdio.h> 

unsigned int result,m,n,i; 
unsigned int binom(int,int); 
int main(){ 

n=10; 
i=0; 


for (i=1; i<2;i++){ 

result = binom(n,i); 

printf("i=%d | %d \n", i, result); 

} 

return 0; 


} 

子:

.text 
    .globl binom 

binom: 
    mov  $0x00, %edx  #for difference calculation 
    cmp  %edi, %esi   #m=n? 
    je  equalorzero   #jump to equalorzero for returning of value 1 
    cmp  $0x00, %esi   #m=0? 
    je  equalorzero  
    cmp  $0x01, %esi   #m=1? 

    mov  %esi,%edx 
    sub  %edi, %edx 
    cmp  $0x01, %edx   # n-m = 1 ? 
    je  oneoronedifference 

    jmp  otherwise 

equalorzero: 
    add  $1, %eax   #return 1 

    call printf 
    ret 

oneoronedifference: 
    add  %edi, %eax   #return n 
    ret 

otherwise: 
    sub  $1, %edi   #binom(n-1,m) 
    call binom  
    sub  $1, %esi   #binom(n-1,m-1) 
    call binom 
    ret 
+1

是你運行的所有命令?我沒有看到兩個'.o'文件的鏈接。你需要做一些像'gcc -o binom binom_main.o binom.o'。 – kaylum

+1

第二次看,聽起來像是一個堆棧溢出的教科書案例(哈哈)。請注意,否則()會得到錯誤'',因此在輸入'main'時絕對不對。 PS:你也使用'printf',這可能是也可能不是一個促成因素。 – Jester

+0

@kaylum是的!我忘了把它包含在OP中。我雖然編輯它。對於那個很抱歉。 –

回答

2

當你使用GDB調試ASM,看看反彙編窗口以及源窗口。 (例如layout asm/layout reglayout next,直到您獲得所需的窗口組合。)請參閱標記wiki的底部,以獲取更多提示和文檔鏈接。

您可以使用stepisi)按指令步進,而不是通過C語句,同時調查由於在返回之前破壞某些東西而導致的asm外部的崩潰。


這看起來像一個錯誤:(?未成年人)

sub  $1, %edi   #binom(n-1,m) 
call binom 
# at this point, %edi no longer holds n-1, and %esi no longer holds m. 
# because binom clobbers them. (This is normal) 

# as Jester points out, you also don't save the return value (%eax) from the first call anywhere. 
sub  $1, %esi   #binom(n-1,m-1) 
call binom 

另一個錯誤是:

cmp  $0x01, %esi   #m=1? 
# but then you never read the flags that cmp set 

另一個嚴重錯誤:

equalorzero: 
    add  $1, %eax   #return 1 # wrong: nothing before this set %eax to anything. 
    # mov $1, %eax    # You probably want this instead 
    ret 
+0

你如何進入asm程序?我從編譯器'(gdb)break binom.s得到這個:12 沒有名爲binom.s的源文件。 ',因爲只有這個'(GDB)SI 0x000000000040054b \t \t 12結果= binom(N,I);從'si'gdb命令中輸入' '。 –

+0

@Egyptian_Coder:爲什麼不用像普通人一樣的調試符號進行編譯? 'gcc -g binom_main.c -Og binom.S -o runtimes'在一個命令中編譯/彙編/鏈接所有內容。我建議'.S'用於手寫asm源代碼,即使它不需要C預處理器。 –

+0

@Egyptian_Coder:但是要設置一個數字地址的斷點,你可以使用'b * 0x000000000040054b'。 (即像指針一樣將地址解引用)。另外,我認爲你所看到的僅僅是你單步執行了呼叫設置的一部分。所以這是一個指令,它是'binom(n,i)'調用者的一部分。如果你設置了gdb來顯示反彙編窗口,就像我建議的那樣,你會看到這個。多走幾步,直到你進入了asm函數。或者只是'''進入asm函數,然後*'si'通過它。 –