`Hello World` на C++ выглядит дружелюбно:.
Ниже — разделы про пример для Linux x86-64 NASM, что такое section .data и что такое section .text, чтобы быстро понять устройство материала, практические ограничения и типовые точки отказа.
Hello World на C++ выглядит дружелюбно:
#include <iostream>
int main() {
std::cout << "Hello, world!" << std::endl;
return 0;
}
На ассемблере тот же вывод может выглядеть заметно длиннее. Не потому что авторы ассемблера хотели мучить новичков, а потому что C++ скрывает много работы за библиотекой и компилятором
- Пример для Linux x86-64 NASM
- Что такое section .data
- Что такое section .text
- Первый syscall: вывести текст
- Второй syscall: завершить программу
- Почему в C++ проще
- Как собрать локально
- Почему online compiler может не принять этот код
- Частые ошибки
- Забыли length
- Скопировали Linux-код в Windows
- Перепутали rax и eax
- Не поняли, что строка — это байты
- Мини-задание
- Ответы на эти вопросы могут быть для вас полезными
- Почему Hello World на ассемблере такой длинный?
- Этот код работает в Windows?
- Что такое syscall?
- Зачем нужен section .data?
- Можно ли начать без Hello World?
- Что почитать дальше по ассемблеру
Пример для Linux x86-64 NASM
section .data
message db "Hello, world!", 10
length equ $ - message
section .text
global _start
_start:
mov rax, 1
mov rdi, 1
mov rsi, message
mov rdx, length
syscall
mov rax, 60
xor rdi, rdi
syscall
Этот пример не универсален для всех online compiler. Он рассчитан на Linux x86-64 и NASM-подобный синтаксис
Что такое section .data
section .data
message db "Hello, world!", 10
length equ $ - message
В .data кладем данные
message db "Hello, world!", 10 создает байты строки. 10 — перевод строки
length equ $ - message считает длину строки
Что такое section .text
section .text
global _start
В .text лежит исполняемый код
global _start сообщает linker-у, что _start — точка входа
Первый syscall: вывести текст
mov rax, 1
mov rdi, 1
mov rsi, message
mov rdx, length
syscall
Для Linux x86-64 системный вызов write обычно использует:
rax = 1— номер системного вызова write;rdi = 1— stdout;rsi = message— адрес строки;rdx = length— длина строки.
syscall передает управление ядру
Второй syscall: завершить программу
mov rax, 60
xor rdi, rdi
syscall
rax = 60 — системный вызов exit
xor rdi, rdi обнуляет rdi, то есть код завершения будет 0
Почему в C++ проще
В C++ std::cout прячет:
- подготовку вывода;
- работу с буфером;
- вызовы операционной системы;
- детали ABI и runtime.
В ассемблере мы видим низкий слой напрямую. Это полезно для понимания, но неудобно для повседневного вывода текста
Как собрать локально
Для NASM на Linux примерный путь:
nasm -f elf64 hello.asm -o hello.o
ld hello.o -o hello
./hello
На Windows, MASM, FASM или SASM команды будут другими. Нельзя просто взять Linux syscall и ожидать, что он заработает в Windows
Почему online compiler может не принять этот код
Причины:
- выбран не NASM;
- выбран 32-bit режим;
- сервис не поддерживает Linux syscall;
- ожидается функция
main, а не_start; - запрещен прямой запуск бинарника;
- другой linker.
В таких случаях лучше взять шаблон именно этого сервиса
Частые ошибки
Забыли length
write должен знать, сколько байт выводить
Скопировали Linux-код в Windows
Windows не использует Linux syscall. Там другой механизм
Перепутали rax и eax
Для x86-64 используются 64-битные регистры вроде rax, rdi, rsi, rdx
Не поняли, что строка — это байты
Ассемблер не хранит "строку" как объект высокого уровня. Мы явно кладем байты в секцию данных
Мини-задание
- Измени текст
Hello, world!. - Добавь перевод строки.
- Измени
lengthавтоматически через$ - message. - Запусти код в среде, которая поддерживает NASM Linux x86-64.
Не начинай с ручного подсчета длины строки. Это лишняя ловушка
Ответы на эти вопросы могут быть для вас полезными
Почему Hello World на ассемблере такой длинный?
Потому что нужно явно описать данные, системный вызов вывода и завершение программы
Этот код работает в Windows?
Нет, это пример для Linux x86-64. Для Windows нужен другой подход
Что такое syscall?
Это инструкция для обращения к ядру операционной системы за системной операцией, например выводом или завершением программы
Зачем нужен section .data?
Там хранятся данные программы, например строка для вывода
Можно ли начать без Hello World?
Да. Для понимания ассемблера даже лучше сначала работать с регистрами и арифметикой
Что почитать дальше по ассемблеру
Если вы собираете тему по шагам, рядом лучше открыть:
- Ассемблер для чайников: первый код без страха — вернуться к простым инструкциям до системных вызовов.
- MASM, NASM, FASM, SASM: что выбрать новичку — понять, почему код зависит от assembler-а и окружения.
- Регистры и флаги процессора простыми словами — разобрать, зачем в примере нужны регистры.
- CMP, JMP, JE, JNZ: условия и циклы в ассемблере — добавить к программе ветвления и маленький цикл.



