asm_x64.md 5.3 KB

movb // копировать 1 байт
movw // копировать 2 байтa
movl // копировать 4 байта
movq // копировать 8 байт

leaq data, %rbx // загрузить адрес переменной data в регистр rbx

~={yellow}Способы адресации=~

// Способ 1: прямая адресация

movw 0x402008, %ax // скопировать 2 байта (адрес 0x402008) в регистр ax
// или по метке
movw M, %ax

// Способ 2: косвенная адресация
// Предварительно загружаем адрес в регистр (3 способа)
movq $0x402008, %rbx
movq $M, %rbx
leaq M, %rbx

// Скопировать в регистр %ax значение из памяти по тому адресу
// который содержиться в регистре %rbx
movw (%rbx), %ax

// Можно указать базовое смещение адреса (положительное - вправо, отрицательное - влево)
movw 8(%rbx), %ax

// Можно указать текущее смещение предварительно загрузив его в регистр
leaq data, %rbx
movq $8, %rcx
movw 0(%rbx, %rcx), %ax

// Можно указать базовое и текущее смещение одновременно
movw 0(%rbx, %rcx), %ax

// Можно указать размер позиции смещения. 
// Вот здесь он равен 2-ум байтам
movw 4(%rbx, %rcx, 2), %ax

~={yellow}Адресация относительно регистра rip=~

%rip - Re-Extended Instruction Pointer - указатель команд. Хранит адрес очередной команды, которая будет выполнена.

Если в качестве базового смещения относительно регистра %rip указана метка, то на место этой метки будет поставлено расстояние в байтах от значения %rip до того адреса, который обозначен данной меткой

movb data(%rip), %al

PIC (PIE) - Position Independent Code Это код, который не зависит от абсолютных адресов. Все ссылки на ячейки памяти относительные (например относительно счетчика команд). Этот код может быть размещен в любой области памяти. Может использоваться при создании динамических библиотек.

~={yellow}Регистр указателя стека=~

%rsp - Re-extended Stack Pointer - Указатель стека В начале выполнения программы содержит адрес, слева от которого можно хранить данные.

Для работы со стеком используются два регистра: %rsp и %rdp

%rsp - адрес левой границы стека %rdp - адрес правой границы стека

Перед использованием стека нужно скопировать содержимое регистра %rsp в %rbp. Для того, чтобы выделить на стеке память под N байтов нужно вычесть число N из регистра %rsp, тем самым "сместить" %rsp влево на N байтов.

// Можно загрузить двухбайтовое значение в стек
movw $0xabcd, 0(%rsp)

// Или 4-ех байтовое
movl 0x12345678, 2(%rsp)

// Но 8-и байтовое загрузить напрямую нельзя
subq %8, %rsp; // выделить 8 байт 
movq $0x0123456789abxdef, %rax // запись в регистр
movq %rax, 0(%rsp) // перемещение в стек

// Загрузка данных в стек частями
subq %1, %rsp; // выделить 1 байт в стеке
movb $0x12, 0(%rsp); // поместить 1 байт в стек

// Далее помещаем два байта в стек
subq %2, %rsp; // выделить 1 байт в стеке
movb $0x1234, 0(%rsp); // поместить 1 байт в стек

// Moжно загрузить в стек 2 (8) байта одной командой
pushw %0x1234

movq $0x0123456789abxdef, %rax // запись в регистр
pushq %rax; 


// Очисить стек
movq %rbp, %rsp

Если в программе применяются функции, использующие стандартизованные соглашения о вызовах функций (например функции стандартной библиотеки языка Си), то стек должен быть выровнен по 16-байтовой границе, т.е. адреса правой и левой границ стека должны быть кратны 16 (Шестнадцатеричное представление должно оканчиваться на 0).

В начале программы адрес правой границы стека изначально кратен 16. Далее, память на стеке нужно выделять порциями, объем которых кратен 16.