Разбор Hello nasm
В посте “Hello nasm assembler” я привел пример программы на ассемблере nasm для Mac OS, но совершенно не рассказал как она работает. Повторю её ещё раз код программы:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
; /usr/local/bin/nasm -f macho64 64.asm && ld -macosx_version_min 10.7.0 -lSystem -o 64 64.o && ./64
global start
section .text
start:
mov rax, 0x2000004 ; write
mov rdi, 1 ; stdout
mov rsi, msg
mov rdx, msg.len
syscall
mov rax, 0x2000001 ; exit
mov rdi, 0
syscall
section .data
msg: db "Hello, world!", 10
.len: equ $ - msg
Комментарии к коду программы:
- В языке nasm
;
обозначает комментарии. Строчка 1. - В строчке 3
global start
для линкера указывается с какого места начинать выполнение программы - Директива
section
задает секции для объектных файлов- .text (строка 5) - для кода, стандартный в Linux
start:
в 7 строчке метка, она отмечает место в коде на которое можно переходитьmov
иsyscall
x86 операторыmov
помещает данные в регистрыsyscall
осуществляет системный вызов и передает управление ядру операционной системы
rax, rdi, rsi, rdx
регистры общего назначения в которые кладутся данные, имеют стандартные способы использованияrax
- аккумуляторrdi
- указатель на получатель для строкrsi
- указатель на источник для строкrdx
- указатель Ввода/Вывода
0x2000004, 0x2000001
константы для идентификации системных вызовов на Windows и Linux будут другие
- .data (строка 19) - для констант, тоже стандартный
- с помощью меток строки 21, 22 можно объявлять переменные, причем
.
значит что переменная локальная и относится к ближайшей сверху метке. Точке может быть несколько. db "Hello, world!", 10
инициализирует данные в выходном файле, объектном section 3.2.1equ $ - msg
присваивает метке константное значение. В данном случае из отступа начала данной метки вычитается отступ msg и мы получаем длину msg в байтах section 3.2.4
- с помощью меток строки 21, 22 можно объявлять переменные, причем
- .text (строка 5) - для кода, стандартный в Linux