Когда только начинал знакомиться с asm комментировал всё, с чем приходилось работать так, как это понимаю я.
Хорошо бы его дополнить, да времени нет =)
Объективная критика приветствуется. Спасибо
redsh (помогал мне когда-то вкурить кое-кто =))
--------------------------------
практически нигде не публиковал, это далеко не полный справочник, тем более не статья. было желание систематизировать то, что знаю, описать эта так - как я понимаю.
--------------------------------
Структура:
1. Типы пересылки данных (сравнение – флаги – переход – выполнение кода, к которому перешли)
2. Регистры (операции над регистрами – адресация – использование переменных)
3. Функции (вызов – принятие ответа – подпрограмма – стандартные подпрограммы)
4. Стек
5. Определения и команды, которые не вошли в другие разделы
Типы пересылки данных
(сравнение – флаги – переход – выполнение кода, к которому перешли)
cmp
Код:
позволяет сравнить два числа:
cmp eax, ebx;
результат сравнение будет содержаться во флагах;
флаги
Код:
биты специального регистра;
обычно хватает знать три состояния:
меньше (bellow или less);
больше (above или great);
равно (equal);
jxx
Код:
проверяет условие xx, если верно, то перескакивает по указанному адресу:
Jxx eax, ebx;
jae xxx;
JE – если равны (Jump if Equal);
JNE – если не равны (Jump if Not Equal);
JAE – беззнаковое больше либо равно;
JB/JA – для работы с беззнаковыми числами;
JL/JG – для работы со знаковыми числами;
jmp xxx;<- безусловный переход к указанной метке
Регистры
(операции над регистрами – адресация – использование переменных)
регистр
Код:
последовательность байт, физически находятся в ЦП;
нужны для вычислений и связи ЦП с внешним миром;
EIP
Код:
содержит указатель на следующую выполняемую команду, недоступен для модификации;
EAX, EBX, ECX, EDX, ESI, EDI, EBP
Код:
32-разрядные регистры (4 байта), так называемые «общего назначение»;
используются в математических операциях, обращении к памяти;
AX, BX, CX, DX
Код:
«младшие половинки» (16-разрядные) регистров (2 байта) EAX, EBX, ECX, EDX;
последние допускают обращение к оным;
AH/AL, BH/BL, CH/CL и DH/DL
Код:
старший и младший байты 16-разрядных регистров AX, BX, CX, DX;
другие виды регистров
Код:
мультимедийные, сегментные, регистры математического сопроцессора, отладочные и другие;
указатель
Код:
регистр заключается в квадратные скобки:
[ebx];
так же можно добавлять смещение:
[ebx + 0x35];
переменная
Код:
объявляются директивами DB (один байт), DW (одно слово), DD (двойное слово) и так далее:
a DD 66h; <- инициализированная переменная двойного слова, содержащая число 66h
b DB ?; <- неинициализированная переменная размером в один байт
знаковость не объявляется;
mov
Код:
копирование (присваивание):
mov eax, ebx;
mov ebx, [edx];
lea или mov с директивой offset
Код:
копирование указателя переменной в регистр (обе команды приводят к одному результату – в edx содержится указатель на переменную b):
lea edx, b;
mov edx, offset b;
inc
Код:
инкремент (увеличение на 1):
inc eax;
add
Код:
увеличение (одного значение на размер другого):
add eax, ebx;
xchg
Код:
меняет местами два значение (swap в C++):
xchg eax, ebx;
Функции
(вызов – принятие ответа – подпрограмма – стандартные подпрограммы)
функция, процедура
Код:
обособленный блок кода, выполняющий определенную функцию;
call
Код:
вызов функции:
call function;
возвращаемое значение
Код:
записывается в регистр:
call function;
mov h, eax; <- в регистре eax возвращенное значение
int
Код:
вызывает подпрограмму:
int x;
int 21
Код:
вызывает подпрограмму, в которой отработает функция вывода текста на экран;
int 16
Код:
вызывает подпрограмму ожидания нажатия клавиши;
int 20
Код:
завершающий код программы (в DOS приложениях);
Стек
стек
Код:
последовательность байтов в памяти, характеризуется определением: первым вошел – последним вышел;
push
Код:
помещает значение в стек:
push eax;
pop
Код:
читает последнее значение из стека:
pop ebx;
Пример на c++:
#include <iostream>
using namespace std;
int main()
{
cout << "push: ";
for(int i = 0; i < 3; i++)
{
__asm
{
push i;
}
cout << i << ' ';
}
cout << endl << "pop: ";
for(int i = 2; i > -1; i--)
{
int a = -1;
__asm
{
pop a;
}
cout << a << ' ';
}
cout << endl;
getchar();
return 0;
}
esp
Код:
указатель стека;
считает байт, находящийся на вершине стека:
mov bl, [esp];
важное условие – квадратные скобки необходимы;
так же можно взять определенное значение стека, путем вычитания из вершины числа i – которое хотим достать, обратите внимание, что стек выровнен на 4, т.е.:
mov ax, [esp+4]; <-второе сверху значение
mov ax, [esp+8]; <-третье сверху значение
mov ax, [esp+i]; <- (i/4-е сверху значение
важно
Код:
не забывайте "обнулять" (отматывать в первоисходное состояние) стек при выходе из программы (примеры обнуления ниже)
обнуление стека
Код:
в самом начале:
mov ebx, esp ;
где нужно "обнулить" (отматать):
mov esp, ebx ;
так же для безболезненного выхода в c++ из программы можно не очищать стек а использовать
exit(0);
Определения и команды, которые не вошли в другие разделы
nop
;
Код:
все что правее - является комментарием и на ход программы не влияет
ассемблерные вставки в языках высокого уровня
Код:
Microsoft Visual C++ ( _asm{}):
#include <iostream>
using namespace std;
int main()
{
int a = 1;
int b = 2;
_asm
{
mov eax, a
mov ebx, b
add eax, ebx
mov a, eax
}
cout << a;
return 0;
}
Pascal (asm end;):
var a, b:integer;
begin
a := 1;
b := 2;
asm
mov eax, a
mov edx, b
add eax, edx
mov a, eax
end;
writeln(a);
end.
программа
Код:
с точки зрения программирования – это последовательность команд, выполняемых процессором и направленных на достижение запланированного результата;
MessageBoxA
Код:
; <- подготовка стека
push 0 ; от этого числа зависит иконка и кнопки нашего сообщения
push 0 ; указатель на заголовок сообщения (0 - заголовка нет)
push offset s0 ; указатель на текст выводимого сообщения
push 0 ; хендл окна с которым связано сообщение (0 - сообщение само по себе, не от кого не зависит)
call ds:MessageBoxA ; вызов диалогового окна
s0 - строка (к примеру char[] в с++)