2015-07-21 3 views
2

Одна из моих сгенерированных функций не вычисляет, что нужно, и я пытаюсь отлаживать ее отдельно. У меня есть ассемблер для этого, и я пытаюсь назвать это из урезанной программы на 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 и как правильно вызвать эту функцию (без изменения кода ассемблера)?

+0

У вас есть исходный код для функции, которую вы отлаживаете? Это было бы намного легче работать, чем сборка. – duskwuff

+0

Каковы значения регистра после сбоя? (только те из строки 17) – donjuedo

+0

SonOfSun и merridius, спасибо, что поймали это. Изменение значения до $ 32. Ничего себе, тогда мне придется записать отчет об ошибке в LLVM, так как этот ассемблер был сгенерирован из его х86-64-бэкэнда из IR, который имел правильные границы цикла :-( – ritter

ответ

2

Проблема возникает из этой линии

cmpq $33, %rsi 

должно быть

cmpq $32, %rsi 

вы получаете доступ к нежелательной в памяти после того, как .quad 31 и приклеить, что в r11 на movq (%r9,%rax), %r11

+0

Мы нашли это почти вместе :) – SonOfSun

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 
Смежные вопросы