Выделение памяти и адресация в сборке - PullRequest
0 голосов
/ 17 января 2019

Я пытаюсь изучить ассемблер и есть пара инструкций, назначение которых мне не совсем понятно.

код C

#include <stdio.h>

int main(int argc, char* argv[])
{
    printf("Argument One - %s\n", argv[1]);
    return 0;
}

Монтаж

    .section    __TEXT,__text,regular,pure_instructions
    .build_version macos, 10, 14
    .intel_syntax noprefix
    .globl  _main                   ## -- Begin function main
    .p2align    4, 0x90
_main:                                  ## @main
## %bb.0:
    push    rbp
    mov rbp, rsp
    sub rsp, 32
    lea rax, [rip + L_.str]
    mov dword ptr [rbp - 4], 0
    mov dword ptr [rbp - 8], edi
    mov qword ptr [rbp - 16], rsi
    mov rsi, qword ptr [rbp - 16]
    mov rsi, qword ptr [rsi + 8]
    mov rdi, rax
    mov al, 0
    call    _printf
    xor ecx, ecx
    mov dword ptr [rbp - 20], eax ## 4-byte Spill
    mov eax, ecx
    add rsp, 32
    pop rbp
    ret
                                        ## -- End function
    .section    __TEXT,__cstring,cstring_literals
L_.str:                                 ## @.str
    .asciz  "Argument One - %s\n"


.subsections_via_symbols

Q1. sub rsp, 32

Почему пространство выделяется для 32 байтов, когда нет локальных переменных? Я считаю, что argc и argv сохраняются в регистрах edi и rsi соответственно. Если это так, что они могут быть перемещены в стек, разве это не потребует только 12 байтов?

Q2. lea rax, [rip + L_.str] и mov rdi, rax

Правильно ли я понимаю, что L_.str имеет адрес строки "" Первый аргумент -% s \ n "? Из того, что я понял, printf получает доступ к этой строке через регистр rdi. Итак, почему не работает ли инструкция mov rdi, L_.str ?

Q3. mov dword ptr [rbp - 4], 0

Почему ноль помещается в стек?

Q4. mov dword ptr [rbp - 8], edi и mov qword ptr [rbp - 16], rsi

Я полагаю, что эти инструкции должны получить argc и argv в стек. Чисто ли принято использовать edi и rsi?

В5. mov dword ptr [rbp - 20], eax

Понятия не имею, что это делает.

1 Ответ

0 голосов
/ 17 января 2019

Q1. sub rsp, 32

Это выделяемое пространство, которое используется для хранения некоторых данных. Хотя он выделяет 32 байта, код использует только первые 16 байтов этого выделенного пространства, qword в [rbp-8] (0: edi) и qword в [rbp-16] (rdi).

Q2. Lea Rax, [Rip + L_.str] и MOV RDI, Rax

Леа получает адрес строки, хранящейся в сегменте «код». Он перемещен в rdi, который используется в качестве одного из параметров для printf.

Q3. mov dword ptr [rbp - 4], 0 ... mov dword ptr [rbp - 8], edi

Здесь хранится 64-битное младшее порядковое значение, состоящее из 0: edi в [rbp - 8]. Я не уверен, почему он это делает, так как он никогда не загружается из этого слова в дальнейшем.

Обычно неоптимизированный код хранит свои аргументы регистра в памяти, где отладочная информация может указывать отладчикам, где их искать и изменять, но неясно, почему clang ноль расширяет argc в edi до 64 бит .

Скорее всего, 0 dword - это нечто отдельное, потому что, если компилятор действительно хотел хранить расширение argc с нулевым расширением, компиляторы будут расширять нулями в регистрах с 32-битным mov, например, mov ecx, edi; mov [rbp-8], rcx. Возможно, этот дополнительный ноль является временным возвращаемым значением, которое он позже решает не использовать из-за явного return 0; вместо неявного падения с конца main? (main особенный, и я думаю, что clang создает внутреннюю временную переменную для возвращаемого значения.)

Q4 mov qword ptr [rbp - 16], rsi ... mov rsi, qword ptr [rbp - 16]

Оптимизация выключена? Он сохраняет rsi, затем загружает rsi из [rbp - 16]. rsi содержит вашу функцию argv arg (== &argv[0]). x86-64 System V ABI передает целочисленные значения / указатели в RDI, RSI, RDX, RCX, R8, R9, затем в стек .

... mov rsi, qword ptr [rsi + 8]

Это загрузка rsi с содержимым argv[1], как 2-й аргумент для printf. (По той же причине, по которой второй аргумент main был в rsi).

Соглашение о вызовах x86-64 System V также является причиной обнуления AL перед вызовом функции varargs без аргументов FP.

В5. mov dword ptr [rbp - 20], eax

Оптимизация выключена? Он хранит возвращаемое значение из printf, но никогда не использует его.

...