Ассемблер позволяет в некоторой точке программы перейти к другой части, то есть выполнить переход. Переходы могут быть условными, то есть выполняться, если только соблюдается некоторое условие, и безусловными - для них не требуется наличие какого-либо условия. В этой статье рассмотрим безусловные переходы.
Для выполнения безусловного перехода применяется инструкция JMP, которая имеет следующие формы:
jmp метка jmp регистр jmp переменная
В первом варианте после инструкции указывается метка, к которой надо перейти. Названия меток произвольные. В языках высокого уровня этой инструкции соответствует оператор goto. Например:
.code main proc mov rdx, 11 jmp m1 ; переходим к метке m1 mov rdx, 22 ; не выполняется m1: ; метка m1 mov rax, rdx ret main endp end
Здесь выполнение процедуры main начинается с копирования в регистр RDX числа 11. Затем выполняется инструкция безусловного перехода jmp
, которая осуществляет переход к метке m1
jmp m1
В итоге последующая инструкция mov, которая помещается в регистр RDX число 22, НЕ выполняется
mov rdx, 22
А выполняются инструкции, которые помещаются после метки m1, то есть копирование в регистр RAX значения из регистра RDX. Для установки метки после ее имени указывается двоеточие:
m1: ; метка m1 mov rax, rdx
То есть в итоге в регистре RAX будет число 11.
Другой пример:
.code main proc mov rax, 22 jmp return ; переходим к метке return mov rax, 33 ; не выполняется return: ret main endp end
Здесь после помещения в регистр RAX числа 22 происходит переход к метке return
, после которой идет выход из функции с помощью инструкции ret
.
Поэтому инструкция
mov rax, 33
выполняться НЕ будет.
Другая форма инструкции jmp в качестве операнда принимает регистр и позволяет перейти к инструкции, адрес которой указан в 64-битном регистре общего назначения:
.code main proc mov rbx, return mov rax, 22 jmp rbx ; переходим к адресу из регистра RBX mov rax, 33 ; не выполняется return: ret main endp end
Здесь в регистр RBX загружается адрес метки return. Поэтому когда инструкции jmp
передается регистр RBX, то будет происходить переход к метке return.
Третий вариант безусловных переходов представляет переход к адресу, который хранится в переменной. Подобная переменная должна представлять тип qword, четверичное слово, которое занимает 64 бит, так как 8 байт - это размер адреса в архитектуре x86-64.
.code main proc mov rax, 23 jmp retPtr ; переходим к адресу из переменной retPtr mov rax, 33 ; не выполняется return: ret retPtr qword return ; переменная retPtr хранит адрес метки return main endp end
Здесь переменная retPtr хранит адрес метки return. Поэтому при выполнении инструкции jmp retPtr
произойдет переход к этой метке. Причем здесь важно подчеркнуть, что
переменная определена в той же процедуре, где располагается метка для перехода, после остальных инструкций.