从 C 调用汇编函数 [英] Calling an assembly function from C

查看:29
本文介绍了从 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆