Почему «sub esp, 96», «lea eax, [esp + 16]» и «mov [esp + 4], eax»?(синтаксис asm intel) - PullRequest
0 голосов
/ 28 ноября 2018

Я пытаюсь выучить ассемблер (синтаксис Intel) путем обратного инжиниринга кода ассемблера, созданного GNU с помощью IDA.У меня очень тяжелое время, чтобы понять ссылки на адреса памяти в ассемблере, и я был бы очень признателен, если бы кто-то прокомментировал приведенный ниже код и объяснил, что на самом деле происходит.

Это следующая программа на C:

#include <stdio.h>

int main(void)
{
    char *input[20];

    scanf("%s", &input);
    printf("%s", input);

    return 0;
}

Сборка с синтаксисом Intel:

push    ebp
mov     ebp, esp

and     esp, -16
sub     esp, 96                             ; char *input[20]

                                            ; scanf("%s", &input)
lea     eax, [esp+16]                       ; move the effective address of [esp+16] into EAX
mov     [esp+4], eax                        ; &input
mov     dword ptr [esp], offset aS          ; %s
call    _scanf

                                            ; printf("%s", input)
lea     eax, [esp+10]                       ; move the effective address of [esp+10] into EAX
mov     [esp+4], eax                        ; input
mov     dword ptr [esp], offset aS          ; %s
call    _printf     

mov     eax, 0
leave
ret

Вопрос 1: Почему компилятор вычел 96 из ESP, когда переменная содержит 20?Для чего нужны все дополнительные байты и как компилятор оказался на этом числе?

sub     esp, 96

Вопрос 2: Почему компилятор выбрал ESP + 16?Почему нет, например, ESP + 5 или ESP + 10?

lea     eax, [esp+16]
mov     [esp+4], eax

Очень ценю вашу помощь.

1 Ответ

0 голосов
/ 28 ноября 2018

sizeof(input), вероятно, равно 80, поскольку input объявлено как char *input[20], то есть массив из 20 указателей (каждый из 4 байтов).

Этот конкретный компилятор (GNU не является компилятором) выравнивает стек по 16 байтам (т.е. поддерживает указатель стека со смещением, кратным 16) и выделяет пространство для параметров одновременно.пролог вместо push их обработки для каждого вызова и затем add esp для очистки стека (см. _cdecl соглашение о вызовах).
Компилятор может просто использовать 8 байтов для параметров (длявсего выделено 88 байт), но 88 не кратно 16, следующее кратное 16 равно 96.

esp - это место для первого параметра, esp+4 второй, esp+8 и esp+12 - отступы для выравнивания, esp+16 до esp+96 - это 80 байтов массива.

esp+5 или esp+10 не подходят, потому что это не то, чего ожидает вызываемый объект.найти аргументы.

Рисование стопки на листе бумаги значительно прояснит ситуацию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...