从C调用汇编函数

时间:2015-07-21 19:51:12

标签: c assembly x86-64

我生成的一个函数没有计算它应该是什么,我试图单独调试它。我有它的汇编程序,我试图从一个剥离的C程序调用它。但是,出于某种原因,我最终在函数中获得了段错误(因此,调用函数似乎工作,但执行失败)。传递参数可能有问题。

功能签名是

void func(int, int, float*, float*, float*);

该函数忽略前两个参数,并接收3个32个浮点数的数组。它会在元素方面添加后两者并将结果按元素存储到第一个数组中。但是,它会以一种奇怪的顺序(而不是线性流过它,这样做的原因不在于这个SO问题的范围内)。这就是汇编代码中offset_arrays的用途。

我检查了x86调用约定(这是我正在使用的架构),前六个整数或指针参数在寄存器RDI,RSI,RDX,RCX,R8和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代码调用函数:

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运行

Program received signal SIGSEGV, Segmentation fault.
func () at f.S:17
17      movss   %xmm0, (%rdx,%r11,4)

所以,这显然是对内存的写入,即对第一个数组的写入。为什么会出现段错误以及如何正确调用此函数(不更改汇编代码)?

2 个答案:

答案 0 :(得分:2)

数组的大小为32,但在函数中,%rsi从0增加到33,后跟jb。这是错误的,访问静态内存的这部分(未分配)会引发分段错误。它应该更改为32.在ubuntu中测试。

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    $32, %rsi
    jb  .LBB0_1

答案 1 :(得分:2)

问题来自这一行

cmpq    $33, %rsi

应该是

cmpq    $32, %rsi

您正在.quad 31之后访问内存中的垃圾并将其粘贴到movq (%r9,%rax), %r11

的r11中