# A * Есть стандартная библиотека, с которой это будет слинковано * return 0 * Очистить стек * # Notices ## X86 * cmovXX (перемещение с условием) * setXX (установка бита с условием) * Аргументы через стек в обратном порядке * Удаление из стека лежит на вызывающем * Результат работы - в al, ax, eax (стандартные типы) * Дробные - в регистрах сопроцессора * cdecl (декларация языка Си) * push/pop - стек * base pointer - для доступа к локальным переменным ``` printf(str, x, y) --- push dword [y] push dword [x] push str call printf -> push L1 jmp printf --- after call: L1: add esp, 12 ; 3 * 4 --- result in eax register (number of printed arguments) ``` * В стек помещается сначала адрес возврата (адрес, откуда вызвали, плюс длина данной инструкции) * ret -> pop ???; jmp ??? * envp, argv, argc - заталкиваются в стек до функции main и ее аргументов * str db, dw, dd, dq (define byte/word/double word) = 12,14,0 (или 'ABCDE', 13, 0), 13 - новая строка, 0 - нулевой байт * x resb(w/d/q) 1 * В глобальных переменных - нуль (по умолчанию) * section (segment - устар.) ``` .text (код) .data (иниц. данные) .rdata (константы) .bss (неиниц. данные) ``` * .bss хранится в виде размера (выделяется в момент запуска) ``` section .text push push call section .data str db '%d',0 section .bss x resd 1 ``` * global (например, main) ``` global main ``` * Добавляет подчеркивания к меткам, _main, например (M$ only) * Вместо линковки вызываем gcc (gcc знает, где стандартная библиотека) * Конвенция fastcall (часть аргументов через регистры, 6 регистров для Linux, в прямом порядке, прочее - в стек в обратном) * Выравнивание стека для x86_64 * Стандартный эпилог и пролог: ``` push ebp mov ebp, esp ... mov edx, [ebp + 8] ; адрес через 2 байта от вершины стека ... mov esp, ebp ; восстанавливаем для функции, вызвавшей данную pop ebp ret ``` * ebp указывает на вершину стека * Пролог, эпилог почти обязателен * sub esp, 32 - для локальных переменных (ebp остался), размер всех локальных переменных функции, обращение к локальным переменным - с минусом от ebp