В посте “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.1
      • equ $ - msg присваивает метке константное значение. В данном случае из отступа начала данной метки вычитается отступ msg и мы получаем длину msg в байтах section 3.2.4