从 C 调用汇编函数 [英] Calling an assembly function from C
问题描述
我生成的一个函数没有计算它应该做什么,我正在尝试单独调试它.我有它的汇编程序,我尝试从一个精简的 C 程序中调用它.但是,由于某种原因,我最终在函数中出现了段错误(因此,调用该函数似乎可以工作,但执行失败).传递参数可能有问题..
One of my generated functions doesn't compute what it should and I am trying to debug it separately. I have the assembler for it and I try to call it from a stripped down C program. However, for some reason I end up getting segfaults in the function (so, calling the function seems to work, but execution fails). There might be something wrong with passing the arguments..
函数签名是
void func(int, int, float*, float*, float*);
该函数忽略前两个参数并接收 3 个数组,每个数组包含 32 个浮点数.它将按元素添加后两者,并将结果按元素存储到第一个数组中.但是,它会以一种奇怪的顺序执行此操作(与通过它线性流式传输相反,这样做的原因不在此 SO 问题的范围内).这就是 offset_arrays
在汇编代码中的作用.
The function ignores the first two arguments and received 3 arrays of 32 floats each. It would add element-wise the latter two and store the result element-wise into the first array. However, it would do that in a kind of weird order (as opposed to streaming linearly through it, the reason for doing this is not in the scope of this SO question). That's what the offset_arrays
are for in the assembler code.
我检查了 x86 调用约定(这是我使用的架构),前六个整数或指针参数在寄存器 RDI、RSI、RDX、RCX、R8 和 R9 中传递.
I checked the x86 calling conventions (that's the architecture I am using) and the first six integer or pointer arguments are passed in registers RDI, RSI, RDX, RCX, R8, and R9.
这里是函数实现:
.text
.globl func
.align 16, 0x90
.type func,@function
func:
.cfi_startproc
xorl %eax, %eax
movabsq $offset_array1, %r9
movabsq $offset_array, %r10
xorl %esi, %esi
.align 16, 0x90
.LBB0_1:
movq (%r9,%rax), %r11
movq (%r10,%rax), %rdi
movss (%r8,%rdi,4), %xmm0
addss (%rcx,%rdi,4), %xmm0
movss %xmm0, (%rdx,%r11,4)
incq %rsi
addq $8, %rax
cmpq $33, %rsi
jb .LBB0_1
retq
.Ltmp0:
.size func, .Ltmp0-func
.cfi_endproc
.type offset_array,@object
.section .rodata,"a",@progbits
.align 16
offset_array:
.quad 0
.quad 16
.quad 1
.quad 17
.quad 2
.quad 18
.quad 3
.quad 19
.quad 4
.quad 20
.quad 5
.quad 21
.quad 6
.quad 22
.quad 7
.quad 23
.quad 8
.quad 24
.quad 9
.quad 25
.quad 10
.quad 26
.quad 11
.quad 27
.quad 12
.quad 28
.quad 13
.quad 29
.quad 14
.quad 30
.quad 15
.quad 31
.size offset_array, 256
.type offset_array1,@object
.align 16
offset_array1:
.quad 0
.quad 16
.quad 1
.quad 17
.quad 2
.quad 18
.quad 3
.quad 19
.quad 4
.quad 20
.quad 5
.quad 21
.quad 6
.quad 22
.quad 7
.quad 23
.quad 8
.quad 24
.quad 9
.quad 25
.quad 10
.quad 26
.quad 11
.quad 27
.quad 12
.quad 28
.quad 13
.quad 29
.quad 14
.quad 30
.quad 15
.quad 31
.size offset_array1, 256
.section ".note.GNU-stack","",@progbits
我尝试从这个 C 代码调用函数:
I try to call the function from this C code:
float f0[32];
float f1[32];
float f2[32];
extern void func(int i0,int i1,float* dest,float* src0,float* src1);
int main(int argc, char *argv[])
{
func(0,0,f0,f1,f2);
}
编译并链接
gcc -o f.o -c -g f.S
gcc -g -o test_f test_f.c f.o
并通过 gdb 运行结果
and running though gdb results in
Program received signal SIGSEGV, Segmentation fault.
func () at f.S:17
17 movss %xmm0, (%rdx,%r11,4)
所以,这显然是对内存的写入,即写入第一个数组.为什么会出现段错误以及如何正确调用此函数(不更改汇编代码)?
So, this is obviously a write to memory, namely to the first array. Why would it segfault and how to call this function correctly (without changing the assembler code)?
推荐答案
问题出自这一行
cmpq $33, %rsi
应该是
cmpq $32, %rsi
您正在.quad 31
之后访问内存中的垃圾,并将其粘贴到 movq (%r9,%rax), %r11
you are accessing the junk in the memory after .quad 31
and sticking that into r11 at movq (%r9,%rax), %r11
这篇关于从 C 调用汇编函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!