Перейти к основному содержимому

Ассемблер

Ассемблер — это программа, транслирующая язык ассемблера в машинный код.

Язык ассемблера — это низкоуровневый язык, предоставляющий более прямой доступ к аппаратным ресурсам компьютера по сравнению с высокоуровневыми языками. Каждая инструкция в языке ассемблера обычно соответствует одной машинной инструкции, что делает его близким к языку машинного кода.

Синтаксис

В этой статье используется синтаксис Intel на примере архитектуры x86-64.

Разновидности синтаксиса

Существует две основные разновидности синтаксиса для языка ассемблера: Intel и AT&T. Они различаются в основном в способе записи операндов и некоторых других деталях.

Синтаксис Intel чаще встречается при работе IBM-совместимыми архитектурами (например, x86 и x86-64), при использовании компиляторов от Intel и Microsoft.

Синтаксис AT&T чаще ассоциируется с миром UNIX-подобных систем. Например, он используется в ассемблерных программах в исходных текстах Linux.

Инструкция формируется из мнепоники (иногда называют опкод, от operation code) и какого-то количества операндов.

Например: mov eax, 5; здесь mov это мнемоника, а eax и 5 — операнды. Эта запись означает "поместить значение 5 в регистр eax".

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

Операнды могут быть трёх типов:

  • непосредственный: значение, которое указано прямо в комадне
  • регистровый: название регистра
  • адресный: адрес ячейки (в т.ч. начало области памяти)

Адресный операнд всегда указывается в квадратных скобках [].

Команды

Рассматривать все команды смысла нет, далее рассмотрены только основные.

Перемещение данных

  • mov <dst> <src> (move)

Арифметические операции

  • add <dst> <src> — складывает два операнда и сохраняет результат в целевом операнде (dst); эквивалентно dst = dst + src

  • sub <dst> <src> (subtract) — вычитает второй операнд из первого и сохраняет результат в целевом операнде; эквивалентно dst = dst - src

  • inc <dst> (increment) — увеличивает значение операнда на 1, эквивалентно dst = dst + 1

  • dec <dst> (decrement) — уменьшает значение операнда на 1, эквивалентно dst = dst - 1

  • neg <dst> (negate) — изменяет знак операнда; эквивалентно dst = -dst

  • mul (multiply)

  • div (divide)

Логические операции

  • and и test – побитовое "и"
  • or – побитовое "или"
  • xor – побитовое исключающее "или"
  • cmp (compare) – сравнение

Переходы

Безусловный переход обозначается командой jump и имеет один операнд — метку, к которой нужно перейти (под меткой понимается адрес инструкции).

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

Эти команды выполняются в связке с другими (например cmp). Предыдущие команды каким-либо образом меняют флаговые регистры, на основе которых затем происходит проверка истинности условия.

Например

cmp rax, rcx
jl label

читается так: сравнить значения в регистрах rax и rcx; если сравнение дало результат "первый операнд меньше второго", перейти к метке label.

Ниже список мнемоник с пояснениями:

  • je – jump if equal
  • jz – jump if zero
  • jl – jump if lower
  • jg – jump if greater
  • jle – jump if less or equal
  • jge – jump if greater of equal
  • jne – jump if not equal
  • jnz – jump if not zero
  • jnl – jump if not less
  • jng – jump if not greater
  • jnle – jump if not less or equal
  • jnge – jump if not greater or equal

Стек

  • call
  • ret (return)
  • push
  • pop

Другое

  • lea <dst> <addr> (load effective address)