C/汇编子程序分段错误

C/汇编子程序分段错误,c,assembly,segmentation-fault,gdb,x86,C,Assembly,Segmentation Fault,Gdb,X86,试图通过GDB运行,并在C主程序进入main函数后继续出现分段错误 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 b

试图通过GDB运行,并在C主程序进入main函数后继续出现分段错误

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;


}

使用gdb调试asm时,请查看“反汇编”窗口和“源”窗口。(例如,
layout asm
/
layout reg
,以及
layout next
,直到您获得所需的窗口组合。)有关更多提示和文档链接,请参见标记wiki的底部

您可以使用
stepi
si
)逐步执行指令,而不是C语句,同时调查asm外部的崩溃,该崩溃是由它在返回前损坏了某些内容引起的


这看起来像一个bug:

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

另一个(次要?)缺陷是:


另一个严重缺陷:

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

这就是你运行的所有命令吗?我看不出这两个
.o
文件链接到了哪里。您需要执行类似于
gcc-obinom binom\u main.obinom.o
的操作。再看看,这听起来像是教科书上的堆栈溢出(哈哈)。注意,否则()中会出现故障
,因此在输入
main
时肯定不正确。注:您使用的
printf
也有错误,这可能是一个促成因素,也可能不是。@kaylum是的!我忘了把它包括在作品里,不过我把它编辑了进去。很抱歉。在asm代码中,您有一个
调用printf
,没有设置任何有效参数。此外,您的
否则
有两个
调用binom
,但第一个调用的结果被丢弃,并且您从未保存
edi
esi
。您如何进入asm程序?我是从编译器
(gdb)break binom.s:12中得到的,没有名为binom.s的源文件(gdb)si 0x000000000040054b 12 result=binom(n,I)si
gdb命令的code>。@Egypt\u编码器:你为什么不像普通人那样用调试符号编译呢
gcc-gbinom_main.c-Og binom.S-o运行时
在一个命令中编译/组装/链接所有内容。对于手工编写的asm源代码,我建议使用
.S
,即使它不需要C预处理器。@Egypt\u Coder:但要在数字地址设置断点,请使用
b*0x00000000004054b
。(即像指针一样取消对地址的引用)。另外,我认为您看到的只是您只需单步执行其中一个指令,这是呼叫设置的一部分。这是一条指令,它是
binom(n,i)
调用方的一部分。如果您像我建议的那样设置gdb以显示反汇编窗口,您就会看到这一点。多走几步,直到进入asm功能。或者只需将
s
输入asm函数,然后将
si
通过它输出。
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