Ассемблер
Как выглядит программа на ассемблере
Программа на ассемблере выглядит как файл с секциями данных и кода, точкой входа, метками и инструкциями процессора. В отличие от обычного языка программирования, здесь явно видно, какие регистры используются, где лежит строка, как вызывается операционная система и как программа завершается
Полный пример Linux x64
Файл hello.asm:
section .data
msg db "Hello from asm", 10
len equ $ - msg
section .text
global _start
_start:
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, len
syscall
mov rax, 60
xor rdi, rdi
syscall
Сборка:
nasm -f elf64 hello.asm -o hello.o
ld hello.o -o hello
./hello
Вывод:
Hello from asm
Это полноценная маленькая программа: она хранит строку, выводит ее и завершает работу
Из каких частей состоит программа
Секция данных:
section .data
msg db "Hello from asm", 10
len equ $ - msg
Здесь хранится строка msg, а len вычисляет ее длину. Число 10 — перевод строки
Секция кода:
section .text
global _start
Здесь находится исполняемый код. global _start сообщает linker, что _start — видимая точка входа
Точка входа:
_start:
Именно отсюда начинается выполнение программы
Что делают регистры в примере
Для Linux x64 системный вызов write использует регистры:
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, len
syscall
Смысл:
rax = 1— номер системного вызоваwrite;rdi = 1— stdout;rsi = msg— адрес строки;rdx = len— длина строки.
Завершение:
mov rax, 60
xor rdi, rdi
syscall
60 — номер exit, а rdi = 0 — код успешного завершения
Как выглядит программа под DOS/TASM
Учебная DOS-программа может выглядеть иначе:
.model small
.stack 100h
.data
msg db 'Hello from DOS$'
.code
main proc
mov ax, @data
mov ds, ax
mov ah, 09h
lea dx, msg
int 21h
mov ax, 4c00h
int 21h
main endp
end main
Здесь используются .model small, int 21h и строка с символом $. Это нормальный вид старой DOS-программы, но он не совпадает с Linux x64 примером
Как выглядит программа как функция
Иногда ассемблерный код — не отдельная программа, а функция для C:
section .text
global add_two
add_two:
mov rax, rdi
add rax, rsi
ret
Такой файл можно собрать в объектный файл и подключить к C-программе. В этом случае нет _start, потому что входной точкой будет main в C
Как понять чужую программу
Смотрите по шагам:
- какая платформа и какой синтаксис;
- где секция данных;
- где секция кода;
- какая точка входа;
- какие регистры используются;
- какие переходы и метки есть;
- как программа завершается.
Если вы видите syscall, это один тип программы. Если видите int 21h, это другой тип. Если видите PROC и ENDP, возможно, это MASM
Частые ошибки
Копируют фрагмент вместо программы
Несколько строк mov и add полезны для обучения, но сами по себе могут не запускаться
Не понимают точку входа
Для прямого Linux-примера нужна _start. Для C-проекта вход может быть в main
Смешивают DOS и Linux
int 21h и syscall относятся к разным окружениям
Что почитать дальше по ассемблеру
Если нужен общий маршрут по теме, откройте рубрику ассемблеру. Для соседних задач пригодятся эти разборы:
- Как выглядит код на ассемблере
- CMP в ассемблере
- CMP в ассемблере: как работает сравнение
- CMP, JMP, JE, JNZ: условия и циклы в ассемблере