Ошибка сегментации в сборке при умножении регистров? - PullRequest
1 голос
/ 09 апреля 2020

Я пытался преобразовать следующий код C в сборку. Вот код C:

typedef struct {
    int x;
    int y;
} point;


int square_distance( point * p ) {
    return p->x * p->x + p->y * p->y;  
}

Мой код сборки выглядит следующим образом:

square_distance:

.LFB23:
    .cfi_startproc
    movl    (%edi), %edx
    imull   %edx, %edx
    movl    4(%edi), %eax
    imull   %eax, %eax
    addl    %edx, %eax
    ret
    .cfi_endproc

При попытке запустить эту программу возникает ошибка сегментации. Может кто-нибудь объяснить, почему? Спасибо! Буду благодарен!

Ответы [ 2 ]

5 голосов
/ 09 апреля 2020

Ваш код 32-битный (x86), но вы применяете соглашение о вызовах, используемое с 64-битным кодом (x64). Очевидно, это может не сработать.

Соглашение о вызовах x86 передает все параметры в стеке.

Соглашение о вызовах x64 передает первый параметр в rdi, второй в rsi третий в rdx, эт c. (Я не уверен, какие регистры используются, если имеется более 3 параметров, это также может зависеть от вашей платформы).

Ваш код предположительно более или менее корректен для кода x64, это будет что-то вроде this:

square_distance:
    movl    (%rdi), %edx
    imull   %edx, %edx
    movl    4(%rdi), %eax
    imull   %eax, %eax
    addl    %edx, %eax
    ret

С кодом x86 параметры передаются в стек, и соответствующий правильный код будет выглядеть примерно так:

square_distance:
    movl    4(%esp), edx
    movl    (%edx), eax
    imull   eax, eax
    movl    4(%edx), edx
    imull   edx, edx
    addl    edx, eax
    ret

В общем Соглашения о вызовах Тема обширна, в зависимости от платформы существуют другие соглашения о вызовах, и даже в пределах одной платформы в некоторых случаях могут существовать различные соглашения о вызовах.

3 голосов
/ 09 апреля 2020

Просто хочу дополнить Jabberwocky ответ . Потому что моей репутации недостаточно, чтобы комментировать.

Способ передачи параметров при вызове функций (также известный как соглашение о вызовах) отличается от архитектур и операционных систем (ОС). Из этой вики

можно узнать много общих соглашений о вызовах. Из вики мы можем узнать, что соглашение о вызовах x64 в * nix передает первые шесть параметров через RDI, RSI, RDX, Регистры RCX, R8, R9, остальные через стек.

...