Метки и безусловный переход jmp

Урок вводит метки и безусловный переход — фундамент всех ветвлений и циклов.

Метка — это имя для адреса в коде; переход на метку меняет значение RIP и продолжает исполнение оттуда.

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

По умолчанию команды идут сверху вниз, потому что RIP сдвигается на следующую. Но команда jmp метка заставляет RIP прыгнуть в другое место — и исполнение продолжается там. Это единственный способ сделать в процессоре циклы, ветвления и функции.

    mov rax, 1
    jmp dalshe     ; перепрыгнуть через следующую строку
    mov rax, 999   ; эта команда НЕ выполнится
dalshe:
    add rax, 10    ; сюда мы прыгнули, rax = 11

Метки — это просто адреса

Когда NASM видит dalshe:, он запоминает адрес этого места. В машинном коде никаких имён нет — jmp превращается в «прибавить к RIP такое-то смещение». Имена нужны только людям; процессор оперирует числами-адресами.

Бесконечный цикл одной командой

Простейший вечный цикл — переход на самого себя:

loop_forever:
    jmp loop_forever   ; RIP всё время возвращается сюда

Чтобы цикл был полезным и завершался, внутри нужна проверка с условным переходом — об этом следующие уроки.

Как работает под капотом

Смоделируем «прыжок» на Python через индекс «команды», имитируя RIP:

program = ["mov", "jmp->4", "skip", "skip", "add"]
rip = 0
trace = []
while rip < len(program):
    cmd = program[rip]
    trace.append((rip, cmd))
    if cmd == "jmp->4":
        rip = 4          # прыжок: меняем RIP напрямую
    else:
        rip += 1         # обычный шаг вперёд
for step in trace:
    print(step)

Вывод:

(0, 'mov')
(1, 'jmp->4')
(4, 'add')

Видно, что команды с индексами 2 и 3 пропущены — RIP перепрыгнул через них. Так же реальный jmp заставляет процессор пропускать или повторять участки кода.

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

  • Забыть двоеточие в определении метки. dalshe без : — это не метка, а попытка использовать имя.
  • Случайно «провалиться» в метку. Если перед меткой нет jmp/ret, код просто продолжит исполняться в неё.
  • Вечный цикл без выхода. jmp на себя без условия внутри зависнет навсегда.

Итог

  • jmp метка меняет RIP и продолжает исполнение с другого места.
  • Метка — это имя адреса; в машинном коде остаются только смещения.
  • Без переходов кода были бы только линейными — нет ни циклов, ни ветвлений.
  • Полезный цикл требует условного перехода внутри, иначе он бесконечен.
Проверьте себя
1. Что технически делает команда jmp метка?
AКопирует метку в rax
BМеняет RIP, продолжая исполнение с адреса метки
CСоздаёт новую функцию
DУдаляет команды до метки
2. Чем является метка в машинном коде?
AСтрокой с именем
BПросто адресом (смещением); имя существует только в исходнике
CОтдельным регистром
DНовой секцией
3. Почему jmp loop_forever на самого себя опасен?
AОн стирает регистры
BБез условия внутри он создаёт бесконечный цикл
CОн слишком медленный
DОн работает только в .data