функции на ассемблере

я немного пофилософствовал о цели стека, и после некоторого кодирования я понял, в чем его сила. Единственное, что лежит у меня в желудке, это как у него с функциями? Я попытался сделать простую функцию для сложения двух чисел с использованием универсальных регистров, но я полагаю, что это не так, как это работает, например, в C. Где все параметры, локальные переменные и где хранится результат?

как бы вы переписали это на ассемблере? (как компилятор для C переписал бы это?)

int function(int a, int &b, int *c){
 return a*(b++)+(*c);
}

я знаю, что этот пример отстой... но так я могу понять все возможности


person Pyjong    schedule 10.03.2010    source источник


Ответы (3)


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

person Aaron Klotz    schedule 10.03.2010
comment
Соглашения о вызовах также известны как двоичный интерфейс приложений (ABI) en.wikipedia.org/wiki/Application_binary_interface. - person Mike DeSimone; 10.03.2010

Во-первых, ссылки (int&) не в C, а только в C++.

Если вы хотите увидеть, что происходит внутри gcc, используйте флаг -S. Вам не нужно иметь реальную программу.

g++ -S func.c

создает файл func.s, который содержит (минус заголовки и т. д., в поле x86):

    .text
.globl __Z8functioniRiPi
__Z8functioniRiPi:
LFB2:
    pushq   %rbp
LCFI0:
    movq    %rsp, %rbp
LCFI1:
    movl    %edi, -4(%rbp)
    movq    %rsi, -16(%rbp)
    movq    %rdx, -24(%rbp)
    movq    -16(%rbp), %rax
    movl    (%rax), %edx
    movl    %edx, %ecx
    imull   -4(%rbp), %ecx
    movq    -24(%rbp), %rax
    movl    (%rax), %eax
    addl    %eax, %ecx
    incl    %edx
    movq    -16(%rbp), %rax
    movl    %edx, (%rax)
    movl    %ecx, %eax
    leave
    ret

Обратите внимание на искажение имени C++ (__Z8functioniRiPi). Теперь мы даем g++ флаг -O2:

    .text
    .align 4,0x90
.globl __Z8functioniRiPi
__Z8functioniRiPi:
LFB2:
    pushq   %rbp
LCFI0:
    movq    %rsp, %rbp
LCFI1:
    movl    (%rsi), %ecx
    movl    %ecx, %eax
    imull   %edi, %eax
    addl    (%rdx), %eax
    incl    %ecx
    movl    %ecx, (%rsi)
    leave
    ret

-O3 дает тот же код; больше нечего оптимизировать.

Получайте удовольствие, играя со сборкой. ^_^

person Mike DeSimone    schedule 10.03.2010

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

person rook    schedule 10.03.2010
comment
Мааан!!! это видео... хуааааа!! все объяснил, даже эти разочаровывающие сегментные регистры теперь мне понятны! БОЛЬШОЕ СПАСИБО!!! - person Pyjong; 10.03.2010