Полный русскоязычный гайд по asmlings — интерактивной песочнице для изучения ассемблера Intel 8086, в которой 16-битный x86-эмулятор написан на Rust. Внутри: что это, как устроено под капотом, как установить, как читать и решать упражнения, разборы реальных задач из репозитория, готовые примеры в examples/ и шпаргалки.
ASMLings — это «rustlings, но для ассемблера 8086». Ты редактируешь
.asm-файл, сохраняешь — эмулятор моментально проверяет, что регистры, флаги и память пришли в нужное состояние, и подсвечивает зелёным/красным.
📢 t.me/rust_code — основной Telegram-канал с уроками и разбором кода для Rust-разработчиков.
🤖 t.me/ai_machinelearning_big_data — полезный Telegram-канал про ИИ, машинное обучение и Big Data: статьи, разборы моделей, новости и практические материалы.
- Что такое ASMLings и зачем оно нужно
- Как это устроено под капотом
- Установка и зависимости
- Первый запуск
- Анатомия упражнения
- Мини-курс по 8086
- Карта памяти 8086
- Синтаксис NASM
- Базовые инструкции с примерами
- Подпрограммы и соглашения о сохранении регистров
- Разборы реальных упражнений из репозитория
- Примеры в репозитории
- Подводные камни 8086
- Как читать дизассемблированный код
- Частые ошибки и отладка
- Шпаргалка инструкций 8086
- Глоссарий
- FAQ
- Куда расти дальше
ASMLings — это набор из ~32 коротких упражнений на ассемблере Intel 8086, выстроенных по возрастанию сложности: от mov ax, 0x1337 до 32-битного сложения через carry flag, циклов, подпрограмм, работы с памятью и стеком.
Что ты получаешь:
- Мгновенный фидбек. Сохраняешь файл — через долю секунды видишь результат: прошёл ассерт или нет.
- Изолированную среду. Не нужно поднимать MS-DOS, DOSBox или возиться с линковщиком — всё крутится во встроенном 16-битном эмуляторе.
- Понятную прогрессию. Каждое упражнение строится на знаниях из предыдущего, а в комментариях прямо в
.asm-файле уже лежит мини-объяснение темы. - Низкий порог входа в системное программирование. Понимание 8086 — это лучший «букварь» к x86-64, ARM64, ядрам ОС, реверсу, эксплойтам, embedded и тому, что генерит
rustc/gcc.
Для кого: Rust-разработчики, бэкендеры и системщики, которые хотят перестать смотреть на ассемблер из godbolt как на магию.
Когда ты сохраняешь .asm-файл, ASMLings выполняет следующий конвейер:
твой .asm файл
│
▼
┌──────────┐ плоский 16-битный бинарь
│ NASM │ ───────────────────────────►
└──────────┘
│
▼
┌────────────────────────────────────┐
│ Rust-эмулятор 8086 (cpu crate) │
│ │
│ - загружает бинарь в виртуальную │
│ память по адресу _start │
│ - декодирует инструкции │
│ - обновляет AX/BX/CX/DX/FLAGS/IP │
│ - крутится до hlt │
└────────────────────────────────────┘
│
▼
┌────────────────────────────────────┐
│ Раннер: парсит ASSERT_* │
│ и сравнивает с финальным │
│ состоянием эмулятора │
└────────────────────────────────────┘
│
▼
✅ или ❌
- NASM компилирует твой файл в плоский 16-битный бинарь (
flatформат, без ELF/PE-обвязки). - Rust-эмулятор 8086 загружает этот бинарь в виртуальную память по адресу
_start. - Эмулятор пошагово декодирует и исполняет инструкции, обновляя виртуальные регистры (
AX, BX, CX, DX, SI, DI, BP, SP, IP), сегментные регистры (CS, DS, ES, SS) иFLAGS. Исполнение длится до встречи сhlt. - Раннер парсит специальные комментарии
; ASSERT_REG,; ASSERT_MEM,; ASSERT_FLAGи сравнивает финальное состояние эмулятора с ожидаемым. - Если все ассерты прошли и ты убрал строку
; I AM NOT DONE— раннер переключается на следующее упражнение.
Watch-режим (asmlings start) сидит на файловой системе через inotify/FSEvents и пере-прогоняет упражнение при каждом сохранении.
🧠 Почему именно 8086, а не x86-64? Потому что 8086 ровно настолько маленький, чтобы за вечер выучить набор инструкций целиком, но при этом достаточно реальный — вся идеология (регистры общего назначения, флаги, стек, сегменты) дошла до современных CPU практически без изменений.
| Зависимость | Зачем нужна | Проверка |
|---|---|---|
| Rust toolchain | поставить и запустить asmlings |
rustc --version |
| NASM | компилятор, который превращает .asm в бинарь |
nasm -v |
| (Linux) libatomic | нужна Rust-эмулятору для 128-битных атомиков | — |
Если Rust ещё не стоит:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh# macOS
brew install nasm
# Ubuntu / Debian
sudo apt install nasm
# Arch Linux
sudo pacman -S nasm
# Fedora / RHEL
sudo dnf install nasm
# Windows (PowerShell)
winget install NASMВариант A — быстро, без компиляции (рекомендую):
cargo install cargo-binstall
cargo binstall asmlingsВариант B — через cargo (с компиляцией всего эмулятора, ~3–5 минут):
cargo install asmlingsВариант C — готовый бинарник: Releases.
Если cargo install asmlings падает с ошибкой линковщика про __atomic_compare_exchange_16 или undefined symbol — твоему линковщику не хватает libatomic:
RUSTFLAGS="-Clink-arg=-latomic" cargo install asmlingsЕсли линкер ругается, что -latomic не найден — поставь библиотеку:
# Ubuntu / Debian
sudo apt install libatomic1
# Arch
sudo pacman -S gcc-libs
# Fedora / RHEL
sudo dnf install libatomic| Редактор | Расширения для .asm |
|---|---|
| VS Code / Cursor | 13xforever.language-x86-64-assembly, maziac.asm-code-lens |
| Neovim | asm_x86.vim, treesitter parser asm |
| Helix | встроенная подсветка asm из коробки |
| JetBrains | плагин «NASM Language» |
# 1. Создай рабочую папку
mkdir asm-course && cd asm-course
# 2. Развернуть упражнения и трекер прогресса
asmlings init
# 3. Запустить watch-режим — оставь этот терминал открытым!
asmlings startПосле asmlings init в текущей папке появится:
asm-course/
├── exercises/ ← задания (.asm файлы)
│ ├── 01_bare_metal.asm
│ ├── 02_halves.asm
│ ├── 03_addition.asm
│ └── ...
└── .asmlings/ ← трекер прогресса
Команды:
asmlings start # watch-режим: пересобирает текущее упражнение при сохранении
asmlings run # одноразово прогнать текущее упражнение
asmlings list # статус всех упражнений (done / todo)
asmlings hint # подсказка по текущему упражнению (если есть)- Открой два окна терминала: в первом —
asmlings start, во втором — обычный shell. - Открой
exercises/в редакторе. Файл со статусомpendingвasmlings list— текущий. - Прочитай комментарии в файле, реши, сохрани.
- Если ассерт упал — посмотри
expectedvsgotв выводе раннера. - Зелёный — удали
; I AM NOT DONE, сохрани ещё раз — переход к следующему.
Открой любой файл из exercises/ — у всех одинаковый каркас. Вот 01_bare_metal.asm целиком, как он лежит в репозитории:
; EXERCISE 1: The Bare Metal
; The 8086 CPU has four main general-purpose 16-bit registers: AX, BX, CX, DX.
; Move the value 0x1337 into the AX register.
;
; ASSERT_REG: AX == 0x1337
global _start
section .text
_start:
; Write your code here:
; I AM NOT DONE
hltРазбираем построчно:
| Строка | Что это |
|---|---|
; EXERCISE 1: ... |
Описание задачи человеческим языком. |
; ASSERT_REG: AX == 0x1337 |
Машиночитаемая проверка. Раннер прочитает это и сравнит с финальным состоянием регистра AX. |
global _start |
Делает метку _start видимой для линковщика. |
section .text |
Секция исполняемого кода. |
_start: |
Точка входа — эмулятор начнёт исполнение отсюда. |
; Write your code here: |
Сюда ты вписываешь решение. |
; I AM NOT DONE |
Сентинель. Пока эта строка есть — упражнение не зачитывается. |
hlt |
Останавливает CPU. Без него эмулятор будет крутить мусор в памяти. |
; ASSERT_REG: AX == 0x1337 ← проверка регистра
; ASSERT_MEM: result == 0x000F ← проверка слова в памяти по метке
; ASSERT_FLAG: ZF == 1 ← проверка флага; EXERCISE 1: The Bare Metal
; ASSERT_REG: AX == 0x1337
global _start
section .text
_start:
mov ax, 0x1337 ; ← наш код
hlt| Регистр | Назначение | Половинки (8 бит) |
|---|---|---|
AX |
Accumulator: арифметика, ввод/вывод | AH (high) / AL (low) |
BX |
Base: адресация ([bx], [bx+si]) |
BH / BL |
CX |
Counter: счётчик циклов и сдвигов | CH / CL |
DX |
Data: умножение/деление, порты I/O | DH / DL |
Особенность 8086: каждый из этих регистров можно резать пополам:
mov ax, 0x0000
mov ah, 0xAB ; AX = 0xAB00
mov al, 0xCD ; AX = 0xABCD| Регистр | Что хранит |
|---|---|
SI |
Source Index — указатель источника для строковых операций |
DI |
Destination Index — указатель приёмника |
BP |
Base Pointer — база стекового фрейма |
SP |
Stack Pointer — вершина стека |
IP |
Instruction Pointer — адрес текущей инструкции |
8086 адресует память по схеме сегмент:смещение. Физический адрес = сегмент * 16 + смещение — 20-битное адресное пространство, 1 МБ.
| Регистр | Назначение |
|---|---|
CS |
Code Segment |
DS |
Data Segment |
ES |
Extra Segment |
SS |
Stack Segment |
| Флаг | Имя | Когда взводится |
|---|---|---|
ZF |
Zero | результат = 0 |
CF |
Carry | беззнаковое переполнение / перенос |
SF |
Sign | старший бит = 1 (отрицательное число) |
OF |
Overflow | знаковое переполнение |
PF |
Parity | чётное число единичных битов |
AF |
Auxiliary | перенос между нибблами |
DF |
Direction | направление строковых операций |
IF |
Interrupt | разрешены ли прерывания |
В упражнениях чаще всего встречаются ZF, CF, SF.
Хотя ASMLings всё абстрагирует, полезно знать, как физически выглядел 1 МБ адресного пространства на реальном PC:
| Адрес | Что лежит |
|---|---|
0x00000–0x003FF |
IVT — Interrupt Vector Table, 256 векторов по 4 байта |
0x00400–0x004FF |
BIOS Data Area |
0x00500–0x07BFF |
свободная conventional memory |
0x07C00–0x07DFF |
boot sector (BIOS грузит сюда первый сектор диска) |
0x07E00–0x9FFFF |
conventional RAM (DOS-программы) |
0xA0000–0xAFFFF |
VGA video memory (графический режим) |
0xB8000–0xBFFFF |
CGA/EGA text mode — сюда писали Hello, World! в DOS |
0xC0000–0xEFFFF |
ROM-расширения (видеокарта, контроллеры) |
0xF0000–0xFFFFF |
BIOS ROM |
💡 Адрес
0xB8000— легендарный. Запишешь туда два байта (символ + атрибут) — на экране появится цветная буква.
mov ax, 0xB800
mov es, ax ; ES = сегмент видеопамяти
mov di, 0 ; смещение
mov al, 'H'
mov ah, 0x07 ; атрибут: светло-серый на чёрном
mov [es:di], ax ; пишем символ в верхний-левый угол экрана; Это комментарий — всё после ';' до конца строки
global _start ; экспортируем точку входа
section .text ; секция кода
_start:
mov ax, 0x1337
hlt
section .data
counter: dw 0x0000 ; объявляем 16-битное слово
message: db "Hi", 0 ; объявляем байты со строкой- Порядок операндов:
mov dest, src— приёмник слева, источник справа. - Числа:
42(dec),0x2Aили2Ah(hex),0b101010(bin),'A'(символ → 0x41). - Память — в квадратных скобках:
mov ax, [0x0200],mov [bx], cx. - Размер задаётся регистром или директивой:
mov word [bx], 1.
| Директива | Размер | Пример |
|---|---|---|
db |
1 байт | db 0x42, 'A', 10 |
dw |
2 байта | dw 0x1337, 0xCAFE |
dd |
4 байта | dd 0xDEADBEEF |
resb N |
резерв N байт | buffer: resb 64 |
| Форма | Пример |
|---|---|
[disp] |
mov ax, [0x0200] |
[bx] или [bp] |
mov ax, [bx] |
[si] или [di] |
mov ax, [si] |
[bx+si], [bx+di], [bp+si], [bp+di] |
mov ax, [bx+si] |
любое выше + disp |
mov ax, [bx+si+4] |
Что нельзя: [ax], [cx], [dx], [bx+bp], [si+di].
mov ax, 0x1234 ; немедленное → регистр
mov bx, ax ; регистр → регистр
mov [0x0200], ax ; регистр → память
mov cx, [0x0200] ; память → регистр
mov [bx], dx ; косвенная адресацияЧто нельзя: mov [bx], [si] — память→память за раз запрещено.
mov ax, 10
add ax, 5 ; ax = 15
sub ax, 3 ; ax = 12
inc ax ; ax = 13
dec ax ; ax = 12
neg ax ; ax = -12 = 0xFFF4mov ax, 6
mov bx, 7
mul bx ; DX:AX = 42
xor dx, dx ; ОБЯЗАТЕЛЬНО перед div маленьких чисел
mov ax, 100
mov bx, 7
div bx ; AX = 14, DX = 2and ax, 0x00FF ; маска: оставить младший байт
or ax, 0x0F00 ; установить биты
xor ax, ax ; ax = 0 ← идиома обнуления
not ax ; инвертировать все биты
test ax, 0x0001 ; как and, но результат не пишетshl ax, 1 ; *2
shr ax, 1 ; /2 (беззнаково)
sar ax, 1 ; /2 (знаково, сохраняет знак)
rol ax, 4 ; циклический сдвиг влевоcmp ax, 5
je equal ; ZF=1
jne not_equal
jl less ; знаковое <
jg greater
jb below ; беззнаковое <
ja above
jl/jg— знаковые сравнения,jb/ja— беззнаковые. Перепутать — получить баг на отрицательных.
mov cx, 5
xor ax, ax
.next:
add ax, 1
loop .next ; cx--, прыгает пока cx != 0
⚠️ ПриCX=0на входеloopсделает 65536 итераций. Защита —jcxzперед циклом.
push ax ; SP -= 2; [SS:SP] = AX
pop bx ; BX = [SS:SP]; SP += 2call label = push IP_next; jmp label. ret = pop IP.
_start:
mov ax, 9
call double ; вызов
hlt ; ax = 18
double:
shl ax, 1
retВ 8086 нет жёсткой ABI, как в System V x86-64. Подпрограмма может портить любые регистры. Две стратегии:
A — caller-saved. Вызывающий сохраняет:
push ax
push bx
call my_func
pop bx
pop axB — callee-saved. Подпрограмма сама сохраняет и восстанавливает:
my_func:
push bx
push cx
; ...
pop cx ; восстанавливать в ОБРАТНОМ порядке
pop bx
retmy_func:
pusha ; push AX, CX, DX, BX, SP, BP, SI, DI
; ...
popa
ret; memset(BX=addr, CX=count, AL=byte)
memset:
push di
mov di, bx
.loop:
mov [di], al
inc di
loop .loop
pop di
retmy_func:
push bp
mov bp, sp
mov ax, [bp+4] ; первый аргумент со стека
add ax, [bp+6] ; второй
pop bp
ret_start:
mov ah, 0xAB
mov al, 0xCD
hlt_start:
mov bx, 0x0010
add bx, 0x0005
hlt_start:
mov ax, 0xBEEF
mov dx, ax
hlt_start:
xor cx, cx
xor dx, dx
hlt_start:
mov ax, 0xCAFE
push ax
pop bx
hlt_start:
mov ax, 0x0005
mov bx, 0x0006
mul bx ; DX:AX = 30
hlt_start:
mov ax, 0x000A
cmp ax, 0x000A
je is_ten
mov bx, 0x0002
jmp end
is_ten:
mov bx, 0x0001
end:
hlt_start:
xor ax, ax
mov cx, 4
.next:
add ax, 3
loop .next
hlt_start:
mov ax, 0x0007
add ax, 0x0008
mov [result], ax
hlt
section .data
result: dw 0x0000_start:
mov ax, 0x0009
call double
hlt
double:
shl ax, 1
ret_start:
mov dx, 0x0001
mov ax, 0xFFFF
mov cx, 0x0000
mov bx, 0x0001
add ax, bx ; CF=1
adc dx, cx ; DX = 1 + 0 + 1 = 2
hltadc (Add with Carry) добавляет ещё и текущий CF. Базовый приём multi-precision arithmetic.
В папке examples/ лежат готовые .asm-файлы с подробными комментариями:
| Файл | Тема |
|---|---|
01_hello_register.asm |
загрузка значения в регистр |
02_register_halves.asm |
работа с AH/AL |
03_arithmetic.asm |
сложение, вычитание, neg |
04_xor_idiom.asm |
идиома обнуления через XOR |
05_stack.asm |
push/pop, обмен через стек |
06_mul_div.asm |
умножение и деление с DX:AX |
07_loop_sum.asm |
сумма 1+2+...+10 через loop |
08_memory.asm |
чтение и запись в память |
09_subroutine.asm |
вызов и возврат, передача через регистры |
10_carry_32bit.asm |
32-битное сложение через CF и ADC |
Подробное описание — в examples/README.md.
Цикл сначала декрементит CX — при входе с CX = 0 получишь 0xFFFF итераций. Защита:
jcxz skip ; если CX=0 — сразу прыжок
.next:
; ...тело цикла...
loop .next
skip:Делимое — пара DX:AX. Если DX содержит мусор, результат будет неожиданным.
xor dx, dx ; ОБЯЗАТЕЛЬНО
mov ax, 100
div bxmov al, 0xFF ; беззнаково = 255, знаково = -1
cmp al, 1
jb less_unsigned ; не прыгнет (255 > 1)
jl less_signed ; прыгнет (-1 < 1)mov [bx], 1 ; ОШИБКА: byte или word?
mov byte [bx], 1 ; ок: 1 байт
mov word [bx], 1 ; ок: 2 байтаСмещение — 16 бит. 0xFFFF + 1 оборачивается в 0x0000 внутри сегмента, а не переходит в следующий.
В CS нельзя положить значение через mov — только через far jmp/call/retf.
Строковые инструкции (movsb, stosb, lodsb) идут по памяти в направлении DF:
cld—DF=0, идём вперёд (SI/DI инкрементируются).std—DF=1, идём назад.
Хорошая привычка — ставить cld в начале процедуры.
godbolt.org — пишешь Rust/C, видишь сгенерированный ассемблер.
pub fn add(a: i32, b: i32) -> i32 {
a + b
}rustc на x86-64 c -O:
add:
lea eax, [rdi + rsi] ; одной инструкцией: eax = rdi + rsi
retpub fn sum_to(n: i32) -> i32 {
let mut s = 0;
for i in 1..=n { s += i; }
s
}sum_to:
xor eax, eax ; s = 0
test edi, edi
jle .done
mov ecx, 1
.loop:
add eax, ecx
inc ecx
cmp ecx, edi
jle .loop
.done:
retУзнаваемо: xor eax, eax для обнуления, cmp + переход, inc для счётчика, ret.
| Симптом | Причина | Решение |
|---|---|---|
nasm: command not found |
NASM не установлен | См. раздел 3.2 |
| Упражнение не зачитывается, ассерты прошли | Не удалена ; I AM NOT DONE |
Удали её |
ASSERT_REG: AX == ... (got 0x0000) |
Не та инструкция или регистр | Проверь, что пишешь в AX, а не BX/AL |
| Бесконечный цикл | Забыл hlt или условие выхода в loop |
Добавь hlt, перепроверь CX |
Странные значения после mul/div |
Результат / делимое в DX:AX |
Учитывай старшее слово, перед div — xor dx, dx |
| Условные переходы «наоборот» на знаковых | jb/ja вместо jl/jg |
Знаковые — jl/jg, беззнаковые — jb/ja |
mov [bx], [si] не компилируется |
Память→память запрещено | Через регистр |
Linker error __atomic_compare_exchange_16 |
На Linux нет libatomic | RUSTFLAGS="-Clink-arg=-latomic" cargo install asmlings |
- Перечитай комментарии в
.asm— там обычно есть подсказка. - Запусти
asmlings run— увидишь, какой ассерт упал. - Закомментируй последние строки, проверь промежуточное состояние.
- Эмулятор молчит — почти всегда нет
hlt.
Пересылка: mov, xchg, lea, push, pop, pushf, popf
Арифметика: add, adc, sub, sbb, inc, dec, neg, mul, imul, div, idiv, cmp
Логика: and, or, xor, not, test
Сдвиги: shl, shr, sal, sar, rol, ror, rcl, rcr
Переходы: jmp, je/jne, jl/jg, jb/ja, jz/jnz, jc/jnc, jo/jno, js/jns, loop, jcxz
Стек/вызовы: call, ret, push, pop, pusha, popa, enter, leave
Строки: movsb, movsw, lodsb, stosb, cmpsb, scasb, rep, repe, repne
Прочее: nop, hlt, int, cld, std, clc, stc, cli, sti
| Инструкция | Условие | Использование |
|---|---|---|
je / jz |
ZF=1 | равно / ноль |
jne / jnz |
ZF=0 | не равно |
jb / jc |
CF=1 | беззнаковое < |
ja |
CF=0 ∧ ZF=0 | беззнаковое > |
jl |
SF≠OF | знаковое < |
jg |
ZF=0 ∧ SF=OF | знаковое > |
js |
SF=1 | отрицательное |
jo |
OF=1 | знаковое переполнение |
jcxz |
CX=0 | CX = 0 (не смотрит флаги!) |
| Идиома | Эквивалент | Зачем |
|---|---|---|
xor reg, reg |
mov reg, 0 |
короче и быстрее |
test reg, reg |
cmp reg, 0 |
короче |
shl reg, 1 |
reg * 2 |
быстрее mul |
shr reg, 1 |
reg / 2 |
быстрее div |
inc reg |
add reg, 1 |
1 байт vs 3 |
lea ax, [bx+4] |
mov ax, bx; add ax, 4 |
одной инструкцией |
- Word — 16-битное значение (2 байта). В 8086 это «родной» размер.
- DWord — 32-битное (double word).
- IVT (Interrupt Vector Table) — таблица обработчиков прерываний в начале памяти.
- MBR (Master Boot Record) — первый сектор диска, который BIOS грузит по
0x7C00. - POST — Power-On Self-Test, что делает BIOS до загрузки ОС.
- REAL mode — режим 8086, 20 бит адресации, без защиты памяти.
- PROTECTED mode — режим 80286+, виртуальная память, привилегии.
- Endianness — порядок байт. x86 — little-endian:
0x1234в памяти как34 12. - NOP — «no operation», 1 байт
0x90, ничего не делает (для выравнивания). - Prefetch queue — очередь предварительной выборки инструкций. У 8086 — 6 байт.
- BCD (Binary Coded Decimal) — каждая десятичная цифра в 4 битах.
- Sentinel (в ASMLings) — строка
; I AM NOT DONE.
Q: Можно ли запускать настоящие 8086-программы (.COM)?
A: ASMLings — учебная песочница, не полный DOS-эмулятор. Для .COM/.EXE — DOSBox-X, 86Box, v86.
Q: Чем 8086 отличается от 8088? A: Только шириной шины данных (16 vs 8 бит). Программисту они идентичны. IBM PC изначально использовал 8088.
Q: Почему задачи только до 32-го? A: Это покрывает почти весь базовый ISA 8086. Дальше — расширения (80186, 80286, FPU), их удобнее изучать на x86-64.
Q: Есть ли смысл учить 8086 в 2026? A: Да. x86-64 — прямой наследник 8086. И 8086 — самый простой способ понять концепции (регистры, флаги, стек, сегменты), которые есть везде, включая ARM64.
Q: Можно использовать инструкции 80286+?
A: Часто да (pusha/popa, shl reg, imm > 1). Но цель упражнений — освоить именно 8086.
Q: Где исходники эмулятора?
A: В asmlings, зависимость cpu crate. Хороший материал для изучения «как написать эмулятор» на Rust.
- 📖 PC Assembly Language — Paul A. Carter (бесплатный PDF).
- 📖 The Art of Assembly Language — Randall Hyde.
- 📖 Modern X86 Assembly Language Programming — Daniel Kusswurm.
- 🔗 felixcloutier.com/x86 — справочник по x86-инструкциям.
- 🔗 godbolt.org — Compiler Explorer.
- 🔗 OSDev wiki — если хочешь написать свою мини-ОС.
- 🦀 Rust + asm: макрос
asm!стабилен с 1.59. - 🔍 Следующие архитектуры: x86-64 → ARM64 → RISC-V.
- 🛠 Реверс-инжиниринг: Ghidra, Binary Ninja, radare2.
- 🎯 Boot sector кодинг: напиши свой 512-байтный «hello, world», который грузится BIOS без ОС.
use std::arch::asm;
fn add_via_asm(a: u64, b: u64) -> u64 {
let mut result: u64;
unsafe {
asm!(
"mov {0}, {1}",
"add {0}, {2}",
out(reg) result,
in(reg) a,
in(reg) b,
);
}
result
}Когда пройдёшь все упражнения, попробуй написать на 8086:
- Strlen — длина ASCIIZ-строки.
- Memcpy — копирование
CXбайт из[DS:SI]в[ES:DI]. - Atoi —
"12345"→ число вAX. - Fibonacci — N-е число Фибоначчи в 16 битах.
- Bubble sort — отсортировать массив из
CXслов по адресуBX.
PR и issue приветствуются.
Гайд — MIT. Проект asmlings — @giacomo-folli.
📢 t.me/rust_code — основной Telegram-канал с уроками и разбором кода для Rust-разработчиков.