在C语言中调用NASM函数
我正在尝试学习x86汇编程序,我想用C调用NASM函数。当我运行我的程序时,我遇到以下错误: 分段故障(堆芯转储) 我尝试了几十种简单测试函数的变体,但每次都在同一位置停止 以下是我的在C语言中调用NASM函数,c,gcc,assembly,segmentation-fault,nasm,C,Gcc,Assembly,Segmentation Fault,Nasm,我正在尝试学习x86汇编程序,我想用C调用NASM函数。当我运行我的程序时,我遇到以下错误: 分段故障(堆芯转储) 我尝试了几十种简单测试函数的变体,但每次都在同一位置停止 以下是我的asm和c文件: 分区asm: global _test _test: push ebp mov ebp, esp push ebx mov eax, [ebp+8] mov ebx, [ebp+12] div ebx
asm
和c
文件:
分区asm:
global _test
_test:
push ebp
mov ebp, esp
push ebx
mov eax, [ebp+8]
mov ebx, [ebp+12]
div ebx
pop ebp
ret
主要条款c:
#include <stdio.h>
extern unsigned int test (unsigned int, unsigned int);
int main(void)
{
printf("%d\n", div(85,5));
return 0;
}
我在虚拟机中使用64位Linux
我的错误是什么?我该如何修复它?您忘记弹出ebx(或者至少按顺序排列堆栈):
现在还不清楚你的问题是否解决了。除了其他问题外,还需要在main.c
中进行函数调用,以匹配div.asm
中的调用。例如,如果您创建了一个汇编函数\u test
,则需要将其声明为extern
,并实际使用main
中的函数。e、 g:
#include <stdio.h>
extern unsigned int _test (unsigned int, unsigned int);
int main(void)
{
printf("%d\n", _test (85,5)); /* you are calling div here, not _test */
return 0;
}
global _test
_test:
push ebp
mov ebp, esp
mov eax, [ebp+8]
xor edx, edx
div dword [ebp+12]
mov esp, ebp
pop ebp
ret
现在,您可以编译、链接和运行测试文件:
$ nasm -f elf -o div.o div.asm
$ gcc -m32 -c -o main.o main.c
$ gcc -m32 -o run div.o main.o
$./run
17
或者对于编译/链接,只需:
$ nasm -f elf -o div.o div.asm
$ gcc -m32 -o run main.c div.o
使用调试器找出它在哪个insn上出错。你看,你有两个问题:推送/弹出不匹配,还有一个div
问题。哦,好的一点,是的,Linux不会把名字和前导的\ucode>弄乱。您正在调用的test
函数甚至不是您组装的\u test
函数!既然它是链接的,我想这个符号一定存在于某个库中吧?再说一遍,FTW。使用-g
编译。如gcc-m32-Wall-Wextra-Og-gmain.c div.o-o run
等一下。您调用了一个名为div的函数,但在代码的任何地方都没有定义它。您在汇编中定义的函数称为“test”,浮点异常是因为您是EBX的EDX:EAX,并且商可能不适合32位寄存器。你没有清除EDX。试着在div前面加上xor edx,edx,以确保被除数的前32位为零。@PaulOgilvie:他说的是C代码。它有一个test()
的原型,但是调用了div()
。您需要恢复调用方的ebx
!最好不要首先使用保留呼叫的寄存器(例如,使用ecx
)。更好的是,div[ebp+12]
@PaulOgilvie:pop ebx的加载部分是必需的。当然addesp,4
(不是addsp,4
),或者leave
的传统mov-esp,ebp
部分将恢复esp
,因此pop-ebp
/ret
将起作用,但仍然存在严重的重击ebx
错误。这不是一个有效的建议。但是Paul,因为他正在Linux上创建一个32位应用程序,CDECL指定某些寄存器需要由函数保留。特别是:寄存器EAX、ECX和EDX被调用者保存,其余被调用者保存。如果EBX没有真正恢复,你以后可能会遇到一些讨厌的bug。一开始它似乎很管用,但最终那个bug会咬到你的屁股。@PeterCordes,没错,应该是esp
,而不是'sp'。Thx。您显示堆栈错误,但您的建议(而不是pop ebx)您可以添加sp,4是错误的。函数需要保留EBX,因此必须在返回之前恢复EBX的值<代码>添加sp,4
修复堆栈,但不会按照恢复EBX。
$ nasm -f elf -o div.o div.asm
$ gcc -m32 -c -o main.o main.c
$ gcc -m32 -o run div.o main.o
$./run
17
$ nasm -f elf -o div.o div.asm
$ gcc -m32 -o run main.c div.o