Ассемблер

Как выглядит программа на ассемблере

Программа на ассемблере выглядит как файл с секциями данных и кода, точкой входа, метками и инструкциями процессора. В отличие от обычного языка программирования, здесь явно видно, какие регистры используются, где лежит строка, как вызывается операционная система и как программа завершается

Полный пример 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

Как понять чужую программу

Смотрите по шагам:

  1. какая платформа и какой синтаксис;
  2. где секция данных;
  3. где секция кода;
  4. какая точка входа;
  5. какие регистры используются;
  6. какие переходы и метки есть;
  7. как программа завершается.

Если вы видите syscall, это один тип программы. Если видите int 21h, это другой тип. Если видите PROC и ENDP, возможно, это MASM

Частые ошибки

Копируют фрагмент вместо программы

Несколько строк mov и add полезны для обучения, но сами по себе могут не запускаться

Не понимают точку входа

Для прямого Linux-примера нужна _start. Для C-проекта вход может быть в main

Смешивают DOS и Linux

int 21h и syscall относятся к разным окружениям

Что почитать дальше по ассемблеру

Если нужен общий маршрут по теме, откройте рубрику ассемблеру. Для соседних задач пригодятся эти разборы:

Подписаться
Уведомить о
guest
0 комментариев
Старые
Новые Популярные

Настройки cookie

0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x