问题
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..
The functions signature is
void func(int, int, float*, float*, float*);
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.
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.
Here' the function implementation:
.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
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);
}
Compiling both and linking with
gcc -o f.o -c -g f.S
gcc -g -o test_f test_f.c f.o
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)?
回答1:
The problem comes from this line
cmpq $33, %rsi
it should be
cmpq $32, %rsi
you are accessing the junk in the memory after .quad 31
and sticking that into r11 at movq (%r9,%rax), %r11
回答2:
The size of the arrays is 32, but in the function the %rsi
is incrementing from 0 to 33 with jb
after it. It is wrong and access this part of static memory(not allocated) raieses a segmentation fault. It should be changed to 32. Tested in 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
来源:https://stackoverflow.com/questions/31548364/calling-an-assembly-function-from-c