Skip to main content

Инструкции

Mov копирование значений.

mov destination, source

destination: регистр или память. Source: регистр, память, число. Одновременно не может из памяти в память. Должны совпадать по размерам. Для расширения нулями меньших регистров (только регистр - регистр):

movsxd dest, source     ; если dest - 64-разрядный операнд и source - 32-разрядный
movsx dest, source      ; для всех остальных комбинаций операндов

Однако с знаком будут проблемы. Для беззнакового расширения нулями movzx: 

mov al, 5
movzx rdi, cx 

Значение регистра AL помещается в самый младший байт регистра RDI. Остальные байты (7 байт) регистра RDI заполняются нулями.

Add / sub сложение и вычитание 

add operand1, operand2  ; operand1 = operand1 + operand2
inc rdi    ; rdi = rdi + 1
sub rdi, rsi    ; rdi = rdi - rsi
dec rdi    ; rdi = rdi - 1

Переходы.

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

JMP - безусловный переход. 

jmp метка
jmp регистр
jmp адрес_в_памяти

Переход по метке: 

global _start
section .text
_start:
    mov rdi, 11         ; RDI = 11
    jmp exit            ; переходим к метке exit
    mov rdi, 22         ; не выполняется
exit:                   ; метка exit
    mov rax, 60         ; 60 - номер системного вызова exit
    syscall             

Переход по адресу в регистре: 

global _start
section .text
_start:
    mov rbx, exit       ; в регистр RBX помещаем адрес метки exit
    mov rdi, 22         ; RDI = 1222
    jmp rbx             ; переходим к адресу из регистра RBX
    mov rdi, 33         ; не выполняется
exit:                   ; метка exit
    mov rax, 60         ; 60 - номер системного вызова exit
    syscall

Переход к адресу в памяти. Переменная должна быть qword, четверичное слово, которое занимает 64 бит. 

global _start
section .text
_start:
    mov rdi, 23         ; RDI = 23
    jmp [exitPtr]       ; переходим к адресу из exitPtr
    mov rdi, 33         ; не выполняется
exit:                   ; метка exit
    mov rax, 60         ; 60 - номер системного вызова exit
    syscall             ; выполняем системный вызов exit  
exitPtr: dq exit      ; переменная exitPtr хранит адрес метки exit  

Условный переход

В регистре eflags 4 бита используются для проверки состояния исполнения предыдущей команды и перехода. Инструкции,  выполняющие математические или логические операции (add, sub, and, or, xor и not) влияют на установку флагов, а инструкции загрузки данных типа mov или lea не влияют.

ФлагОписаниеКомандаОписание
CFФлаг переноса. Беззнаковое переполнение (сумма с переносом или вычитании с заимствованием).jcпереход к метке, если флаг переноса установлен
  jncпереход, если флаг переноса НЕ установлен


clcсброс флага переноса


setcустановка флага переноса
OFФлаг переполнения. Переполнение со знакомjoпереход к метке, если флаг переполнения установлен


jnoпереход к метке, если флаг переполнения не установлен
SFФлаг знака. Если старший бит результата установлен. То есть флаг знака отражает состояние старшего бита результата.jsпереход к метке, если флаг знака установлен


jnsпереход к метке, если флаг знака не установлен
ZFФлаг нуля. Если результат вычисления дает 0jzпереход к метке, если флаг нуля установлен


jnzпереход к метке, если флаг нуля не установлен

Сохранение/восстановление состояния


Порядок битов для обоих операций:

    1. Флаг переноса (CF)
    2. Всегда равен 1

    3. Флаг паритетности (PF)

    4. Всегда равен 0

    5. Дополнительный флаг переноса (AF)

    6. Всегда равен 0

    7. Флаг нуля (ZF)

    8. Флаг знака (SF)

Биты 1, 3, и 5 не используются.

lahfкопирует флаги состояния из регистра eflags в регистр ah


sahfсохраняет флаги состояния из регистра ah в регистр eflags

Пример перехода 

global _start
section .text
_start:
    mov al, 255
    add al, 3       ; AL = AL + 3
    jc carry_set    ; если флаг переноса установлен, переход к метке carry_set
    mov rdi, 2      ; если флаг переноса не установлен, RDI = 2
    jmp exit
carry_set:          ; если флаг переноса установлен
    mov rdi, 4      ; RDI = 4
exit:               ; метка exit
    mov rax, 60
    syscall

Сравнение cmp (от compare) сравнивает значения и устанавливает флаги. Результат сравнения используется для условного перехода. 

cmp left_operand, right_operand

Могут участвовать регистры, переменные, непосредственные операнды. Если сравнивается непосредственный операнд, то он указывается вторым. Оба операнда целые числа, числа с плавающей точкой НЕ сравниваются.

Cmp вычитает второй из первого и устанавливает флаги кода условия на основе результата вычитания. Cmp не сохраняет результат вычитания. Аналогичные команды для получения результатов сравнения:

КомандаОписание
jeпроверяет ZF == 1 выполняет переход, если оба операнда равны. Эквивалентна инструкции jz
jneпроверяет ZF == 0 выполняет переход, если оба операнда не равны.
ja / jnbeпроверяет одновременно СF == 0 и ZF == 0. Переход, если первый операнд больше второго. Оба операнда беззнаковые.
jae / jnbпроверяет СF == 0 Переход, если первый операнд больше или равен второму. Оба операнда беззнаковые. Аналогичен инструкции jnc
jb / jnaeпроверяет условие СF == 1 и выполняет переход, если первый операнд меньше второго. Оба операнда беззнаковые. Аналогичен инструкции jc.
jbe / jnaпроверяет одновременно два условия СF == 1 и ZF == 1 (достаточно, чтобы выполнялось хотя бы одно из этих условий). Выполняет переход, если первый операнд меньше или равен второму. Оба операнда беззнаковые.
jg / jnleпроверяет одновременно два условия SF == OF и ZF == 0 (оба условия должны быть истинными). Выполняет переход, если первый операнд больше второго. Оба операнда со знаком.
jge / jnlпроверяет условие SF == OF и выполняет переход, если первый операнд больше или равен второму. Оба операнда со знаком.
jl / jngeпроверяет условие SF != OF (флаги SF и OF не должны быть равны) и выполняет переход, если первый операнд меньше второго. Оба операнда со знаком.
jle / jngпроверяет одновременно два условия SF != OF и ZF == 1 (достаточно, чтобы выполнялось хотя бы одно из этих условий). Выполняет переход, если первый операнд меньше или равен второму. Оба операнда со знаком.

Через / - одинаковые операторы, и машинный код одинаковый.

Циклы

global _start
 
section .text
_start:
    mov rcx, 5
    mov rdi, 0
loop:
    add rdi, 2      ; RDI = RDI + 2 
    dec rcx         ; RCX = RCX - 1 
    jnz loop        ; если флаг нуля НЕ установлен, переход обратно к метке loop         
    mov rax, 60
    syscall