从 C 调用汇编函数时出现分段错误错误
Posted
技术标签:
【中文标题】从 C 调用汇编函数时出现分段错误错误【英文标题】:Segmentation fault error when calling assembly function from C 【发布时间】:2022-01-04 19:44:50 【问题描述】:我目前正在尝试将汇编函数链接到我的 C 代码驱动程序以完成大学作业。在执行程序时,我得到一个 seg fault 错误。
下面将包括我的 C 文件、ASM 文件中的内容以及来自 GDB 调试器的信息。
C 代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void add(char*, char*); //would extern be needed here maybe?
int main()
int choice;
char num1[3];
char num2[3];
printf("Welcome to the back and forth program!\n\n");
do
printf("What would you like to do?\n\n");
printf("1. Add two numbers together.\n");
printf("2. Find if a string is a palindrome. (ASM Version)\n");
printf("3. Find the factorial of a number.\n");
printf("4. Find if a string is a palindrome. (C Version)\n");
printf("5. Exit Program.\n\n");
printf("choose 1-5: ");
scanf("%d", &choice);
getchar();
while(choice < 1 || choice > 5)
printf("\nPlease choose an option between 1 and 5.\n");
scanf("%d", &choice);
getchar();
switch(choice)
case 1:
printf("\n*Add two numbers together*\n\n");
printf("Please enter a number: ");
fgets(num1, 1024, stdin);
num1[strlen(num1) - 1] = '\0';
printf("\nPlease enter a second number: ");
fgets(num2, 1024, stdin);
num2[strlen(num2) - 1] = '\0';
add(num1, num2);
printf("\nResult: %s\n", num2);
case 2:
case 3:
case 4:
case 5:
printf("\nThanks for using!\n");
break;
while(choice != 5);
return 0;
这里需要注意的一点是,我的教授特别说明我将这两个数字作为字符串读取,然后在汇编中使用atoi()
函数将字符串转换为int。
现在,我的 ASM 代码:
BITS 32
GLOBAL add
EXTERN atoi
section .data
section .bss
section .text
add:
push ebp
mov ebp, esp
push eax
call atoi
push ebx
call atoi
mov eax, [ebp+8]
mov ebx, [ebp+12]
add eax, ebx
pop ebx
ret
由于我需要从我的 Assembly 函数中调用 atoi()
,因此我认为有必要使用堆栈。
最后,GDB 调试器在说什么:
Program received signal SIGSEGV, Segmentation fault. 0xffffcdbc in ?? ()
关于调试器错误的说明:在单步执行程序时,一旦到达add(num1, num2)
,就会出现此错误。
对于其他一些重要信息,我正在使用 GCC 编译器、NASM 编译器、Intel Assembler i386,并通过 VirtualBox 在虚拟机中运行 Debian 10 x86_64。
任何关于此事的帮助将不胜感激!
【问题讨论】:
pop ebx
可能是pop ebp
的拼写错误?
【参考方案1】:
我看到的第一个问题是你用的:
fgets(num1, 1024, stdin);
但是num1只有3个字节作为缓冲区,但这不是分段错误的根本原因。
另一个问题是您将add
函数声明为:
void add(char*, char*);
。我认为将其声明为 int add(char*, char*);
并将此函数的结果用作两个数字的总和会更容易。
问题出在汇编代码中,您没有使用正确的参数。例如在这部分:
push eax
call atoi
push ebx
call atoi
您使用eax
和ebx
作为atoi
的参数,但add
函数的参数在[ebp + 8]
和[ebp+12]
中。调用后需要确保栈是干净的,需要使用add esp, 4
(因为只有一个参数)
要记住的另一件事是,在call atoi
之后,结果将存储在eax
寄存器中,因为您在atoi
之后调用atoi
,您将丢失第一个结果。您需要存储第一个atoi
(在堆栈/局部变量上)的结果,然后将其添加到第二次调用atoi
的下一个结果中。我将把我的 C 代码和程序集版本放在 32 位上。
C 代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int add(char*, char*); //would extern be needed here maybe?
int main()
int choice;
int sum;
char num1[3];
char num2[3];
printf("Welcome to the back and forth program!\n\n");
do
printf("What would you like to do?\n\n");
printf("1. Add two numbers together.\n");
printf("2. Find if a string is a palindrome. (ASM Version)\n");
printf("3. Find the factorial of a number.\n");
printf("4. Find if a string is a palindrome. (C Version)\n");
printf("5. Exit Program.\n\n");
printf("choose 1-5: ");
scanf("%d", &choice);
getchar();
while(choice < 1 || choice > 5)
printf("\nPlease choose an option between 1 and 5.\n");
scanf("%d", &choice);
getchar();
switch(choice)
case 1:
printf("\n*Add two numbers together*\n\n");
printf("Please enter a number: ");
scanf("%s", num1);
printf("\nPlease enter a second number: ");
scanf("%s", num2);
sum = add(num1, num2);
printf("\nResult: %d\n", sum);
case 2:
case 3:
case 4:
case 5:
printf("\nThanks for using!\n");
break;
while(choice != 5);
return 0;
汇编代码:
BITS 32
GLOBAL add
EXTERN atoi
section .data
section .bss
section .text
add:
push ebp
mov ebp, esp
push dword [ebp + 8]
call atoi
add esp, 4
push eax
push dword [ebp + 12]
call atoi
add esp, 4
pop ecx
add eax, ecx
leave
ret
【讨论】:
太棒了!所以,我最初也有同样的想法,将add
函数作为 int 函数,但出于某种奇怪的原因,我的教授要求我将该函数作为 void ... 感谢您指出您所做的事情!我还在学习如何在 ASM 和 C 之间传递东西,这很有帮助。
那么 asm 文件需要进行一些更改。您需要用来自eax
的整数覆盖[ebp+8]
或[ebp+12]
。但要小心,因为[ebp+8
和[ebp+12]
是地址,而eax 基本上是一个整数。
最好写mov [ebp-4], eax
而不是add esp, 4
push eax
。
@SepRoland 是的,但更难理解。
@MocanuGabriel 我一定会研究如何做到这一点@Sep Roland 我也会研究并弄清楚那是什么哈哈!我的 ASM 课程只是一门入门课程,但我很想了解更多。谢谢你们的帮助和意见!以上是关于从 C 调用汇编函数时出现分段错误错误的主要内容,如果未能解决你的问题,请参考以下文章