Найти тему

Шпаргалка по Assembler

PS

Решил поделиться своими заметками по разным тематикам. Сразу предупреждаю, что они могут быть малого объёма и не раскрывать тему полностью (какие-то базовые/начальные вещи). Я писал их для себя, чтобы быстрее въехать в какой-либо материал, либо когда понадобиться - открыть и вспомнить, что и как (короче, использую как шпаргалки).

Для первой статьи в таком жанре выбрал заметки по языку Assembler (языку АссемблерАААА, я привык просто Ассемблер).

Assembler

Это машинно-ориентированный язык программирования низкого уровня. Если вам необходимо углубиться в него, то существует большое количество книг, статей и видеоуроков.

Структура программы

.586 ; размещены команды начиная с версии 586

.MODEL FLAT, STDCALL ; плоская модель памяти, отчистка стэка

;PUBLIC fn ; вставляется при работе с С++

.DATA ; (var)

.CODE ; блок программы, содержащий код

START: ; метка

OPERATORS

;fn ENDP

END START

Подключение к C++

В файле <name>.с\.cpp после (это не тег, а знак решетки)#include.

extern "C" тип_возвращаемого_значения __stdcall fn(переменные);

Если в ассемблер передаются переменные, то их нужно вытащить из стэка командой pop.

Например: в С++ (fn(a);) в asm (pop EAX)

Регистры

  • EAX - аккумулятор !
  • EBX - база ! регистры общего назначения
  • ECX - счетчик ! могут хранить любую информацию
  • EDX - регистр данных !
  • EBP - указатель базы
  • ESP - указатель стека (самое верхнее значение)
  • ESI - индекс источника
  • EDI - индекс приемника
  • EIP - указатель текущей команды
  • EFLAGS - регистр флагов

Флаги

  • O - флаг переполнения
  • A - доп. флаг переноса
  • P - флаг четности (1 - когда четное количество 1 в двоичном числе)
  • Z - флаг нуля (если вернул ноль, то флаг = 1)
  • S - флаг знака (отрицательное - s = 1)
  • C - флаг переноса (было ff, прибавили 1, флаг стал = 1)

Команды

(Нельзя оформить двухуровневый список, поэтому таким образом)

  • ADD - сумма

ADC - с переносом

XADD - например, XADD EAX(значение = 9),ECX(значение = 1) тогда будет EAX=A, ECX=9, то есть обмен + сложение

  • SUB - вычитание

SBB - с переносом

  • MUL - умножение

IMUL - со знаком

  • DIV - деление

IDIV - со знаком

  • MOV - копирование значения (2 в 1)

MOVSX, MOVZX - копируют значения 2го (например, размер 4) в 1ое (размер 8) и заполняет левую сторону (F-отриц или 0-положит)/(0)

  • LEA - копирование адреса (первый операнд - это регистр общего назначения, а второй - адрес ячейки памяти)
  • NEG - изменение знака
  • PUSH - помещение в стек (PUSH [401008] - помещение в стек содержимого ячейки в памяти по адресу 401008, но в обратном порядке)

PUSHAD = PUSH EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI

PUSHA = PUSH AX,...

  • POP - извлечение из стека

POPAD = POP EDI, ESI, EBP, ESP, EBX, EDX, ECX, EAX

POPA = POP DI,...

  • LOOP - управление циклом с ECX
  • INC - инкремент
  • DEC - декремент
  • CMP - сравнение двух операторов (например, CMP EAX, ECX и если они равны то активируется флаг Z, если не равны, то S=1 когда ECX>EAX)
  • SHL - сдвиг влево
  • SHR - сдвиг вправо
  • NOP - no operation
Вот так я нарисовал себе в заметках
Вот так я нарисовал себе в заметках

Логические инструкции

  • AND (AND EAX,ECX) - побитное "и"
  • OR
  • XOR
  • NOT

Переходы

Все инструкции переходов принимают один операнд, задающий адрес, на который должна перейти программа.

  • JMP – переход
  • JE, JZ – переход, если равно нулю
  • JNE, JNZ – переход, если не равно нулю
  • JS – переход, если знак отрицателен
  • JNS – переход, если знак не отрицателен
  • JP, JPE – переход, если чётно
  • JNP, JOP – переход, если нечётно
  • JO – переход, если произошло переполнение
  • JNO – переход, если переполнения не произошло
  • JB, JNAE – переход, если ниже
  • JNB, JAE – переход, если выше или равно
  • JBE, JNA – переход, если ниже или равно
  • JNBE, JA – переход, если выше
  • JL, JNGE – переход, если меньше
  • JNL, JGE – переход, если больше или равно
  • JLE, JNG – переход, если меньше или равно
  • JNLE, JG – переход, если больше
  • CALL address - вызывает функцию по адресу
  • RET (RETN) - возвращает нас на следующую строку после CALL

Циклы

перед началом цикла

XOR ECX,ECX ; обнуляем

ADD ECX,15 ; записываем количество итераций в счетчик

цикл на простых командах:

DEC ECX ; декремент счетчика

; тело цикла

TEST ECX,ECX ; проверка на ноль, если не ноль, то z=0

JNE метка_начала_цикла ; если z=0, то прыграет на начала цикла (на dec)

цикл на LOOP:

LOOP метка_начала_цикла

Существуют некоторые вариации инструкции LOOP:

LOOPZ, LOOPE Цикл повторяется пока флаг Z установлен

LOOPNZ, LOOPNE Цикл повторяется пока флаг Z сброшен

Обе вариации работают как обычный LOOP, т.е. повторяют тело цикла пока счётчик не достигнет нуля, уменьшая на 1 значение счётчика при каждом повторе. В добавок, LOOPZ и LOOPNZ ещё проверяют значение флага Z и прерывают цикл если Z сброшен или установлен соответственно. Таким образом, цикл можно прервать досрочно (до того как ECX достигнет нуля), используя флаг Z.

Цепочечные инструкции

MOVS - Данная инструкция копирует данные из одного адреса в другой. Адрес источника хранится в регистре ESI, адрес приёмника - в EDI. Предварительно инициализируем ESI адресом ячейки, содержимое которой нужно скопировать (источник), и EDI - адресом ячейки, в которую нужно осуществить копирование (проёмник). MOVS копирует 4x-байтные значения = MOVSD. Существуют ещё инструкции MOVSW и MOVSB, копирующие 2 байта (WORD) и 1 байт (BYTE) соответственно.

REP - Это префикс, который можно использовать перед некоторыми инструкциями, в частности MOVS. Данный префикс указывает, что текущую инструкцию нужно выполнить ECX количество раз.

LODS - Данная инструкция загружает данные из источника (ESI) в аккумулятор (EAX). Есть ещё инструкции LODSW и LODSB для загрузки 2-байтовых (WORD) и 1-байтных (BYTE) значений соответственно.

STOS - Сохраняет значение аккумулятора (EAX) по адресу приёмника EDI. Можно использовать префикс REP для автоповторения и существуют 2-байтовая и 1-байтная версии: STOSW и STOSB.

CMPS - Осуществляет сравнение ячеек, указанных в источнике (ESI) и приёмнике (EDI). Сравнение кроет за собой арифметическую операцию вычитания и, если значения равны, то в результате мы получаем ноль, а это значит, что флаг Z будет установлен.

Способы адресации

1. Прямая адресация:

MOV dword ptr [00513450], ecx

MOV ax, word ptr [00510A25]

MOV al, byte ptr [00402811]

CALL 452200

JMP 421000

2. Косвенная адресация:

MOV dword ptr [eax], ecx

CALL EAX

JMP [ebx + 4]