Одна из моих сгенерированных функций не вычисляет, что нужно, и я пытаюсь отлаживать ее отдельно. У меня есть ассемблер для этого, и я пытаюсь назвать это из урезанной программы на C. Однако по какой-то причине я получаю segfaults в функции (так что вызов функции, похоже, работает, но выполнение не выполняется). Там может быть что-то не так с передачей аргументов ..Вызов функции сборки из 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
Я пытаюсь вызвать функцию из этого кода С:
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 как и связывающий с
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)
Таким образом, это, очевидно, запись в память, а именно в первый массив. Зачем это было бы segfault и как правильно вызвать эту функцию (без изменения кода ассемблера)?
У вас есть исходный код для функции, которую вы отлаживаете? Это было бы намного легче работать, чем сборка. – duskwuff
Каковы значения регистра после сбоя? (только те из строки 17) – donjuedo
SonOfSun и merridius, спасибо, что поймали это. Изменение значения до $ 32. Ничего себе, тогда мне придется записать отчет об ошибке в LLVM, так как этот ассемблер был сгенерирован из его х86-64-бэкэнда из IR, который имел правильные границы цикла :-( – ritter