PDA

Просмотр полной версии : [Информация] Экскурс в команды ассемблера


Ivan_32
19.02.2009, 04:26
Команда MOV - пересылка данных RtM или MtR
Семантика:
MOV r8/r16/r32,m8/m16/m32
MOV m8/m16/m32,r8/r16/r32
MOV r8/r16/r32,r8/r16/r32
Команда копирует данные из регистра в память или наоборот так же возможна пересылка из регистра в регистр. В выскоуровневых языка реализована в виде присваивания.
MOV EAX,dword ptr[rMem]
Перешлет двойное слово расположенное по адресу rMem в регистр EAX
MOV EAX,0Ah
Преобразует 0Ah в двойное слово - 0000000Ah и перешлет его в EAX
Важно понимать что если вы работаете с каким то регистром и пересылаете в него данные, то размер операнда будет преобразован в размер регистра.
Незаполненые участики операнда заполняются нулями. Вот как в нашем примере - 0Ah ведь на самом деле по размер байт, но он дополнен нулями, что
бы занулить остальные 3 байта регистра. Вот скажем команда.
MOV AX,0Ah
Дополнит 0Ah до вида 000Ah - слова. Таким образом из всего EAX-а занулится только один байт, тоесть E-часть останется неизменной.


Команда ADD - сложение двух операндов RtM или MtR
Семантика:
ADD r8/r16/r32,m8/m16/m32
ADD m8/m16/m32,r8/r16/r32
ADD r8/r16/r32,r8/r16/r32
Команда выполняет сложение двух чисел, находящихся в регистре и памяти или же в регистре и регистре.
ADD EAX,dword ptr[rMem]
Прибавит к EAX двойное слово которое находится по адресу rMem.
ADD EAX,0Ah
Прибавит 0Ah к EAX . Тут никаких преобразований не происходит так как не требуется. Но размер операнда прибавляемого к операнду применику,
должен соотвествовать размеру последнего. Если при сложении двух операндов происходит переполнение операнда применика -
самый старший бит результата сложения(именно тот который не помещаеться в операнд применик) устанавливается как флаг CF(Carry Flag).
В ассемблере предусмотрены две инструкции которые как раз дают возможность работать с этим битом.

Команда SUB - вычитание двух операндов RtM или MtR
Семантика:
SUB r8/r16/r32,m8/m16/m32
SUB m8/m16/m32,r8/r16/r32
SUB r8/r16/r32,r8/r16/r32
Команда выполняет сложение двух чисел, находящихся в регистре и памяти или же в регистре и регистре.
SUB EAX,dword ptr[rMem]
Прибавит к EAX двойное слово которое находится по адресу rMem.
SUB EAX,0Ah
Вычтет 0Ah из EAX . Аналогично ADD, тут преобразования тоже не происходят. Но как и при ADD, размер операндов должен быть одинаковым.
Флаг CF(Carry Flag - флаг переноса) не устанавливается, по понятным причинам.


Команда ADC - сложение двух операндов, при переполнении операнда применика, лишний бит устанавливается в CF.
Семантика:
ADC r8/r16/r32,m8/m16/m32
ADC m8/m16/m32,r8/r16/r32
ADC r8/r16/r32,r8/r16/r32
Как видно семнтика аналогична ADD.
MOV EAX,0FFFFFFFFh ;Это для наглядности.
ADC EAX,1
В EAX окажутся нули, а вот CF будет установлен в TRUE(1).

Команда SBB - вычитание двух операндов, с заемом из CF.
Семантика:
SBB r8/r16/r32,m8/m16/m32
SBB m8/m16/m32,r8/r16/r32
SBB r8/r16/r32,r8/r16/r32
Семантика аналогична SUB, а вот принцип работы несколько иной.
Допустим произошло переполнение например такое:
MOV EAX,0FFFFFFFFh
ADC EAX,1
Теперь происходит наша команда:
SBB,EAX,0Ah
Как это работает? Очень просто. На самом деле 0Ah отнимается не от того что в EAX а от совсемстного числа состоящего из старшей части - CF и младшей EAX
Тоесть фактически в качестве первого операнда выступает число 100000000h. Результатом будет то что в EAX окажеться 0FFFFFFF5h.

Команда LEA - вычисление эффективного адреса переменной.
Семантика:
LEA r32,m32/m16/m8
Вычисляет эффективный адрес переменной в коде и пересылает его в первый операнд.
Например код:
LEA EAX,sPrintf
Вычислит эффективный адрес переменной sPrintf и поместит его в EAX

Ivan_32
19.02.2009, 19:10
Команда AND - логическое И для двух операндов, результат сохраняется в первом.
Семантика:
AND r8/r16/r32,m8/m16/m32
AND m8/m16/m32,r8/r16/r32
AND r8/r16/r32,r8/r16/r32
Для начала выясним что же такое логическое И. В Дискретной математике эту операцию называют конъюнкцией или логическим умножением.
В ассемблере эта операция работает с битами.
Таблица Истинности:
<table width="121" border="1" bordercolor="black" cellpadding="2" cellspacing="0" height="170"><tbody><tr><td width="20" align="center">OP1</td><td width="20" align="center">OP2</td><td width="20" align="center">AND</td></tr><tr><td width="20" align="center">1</td><td width="20" align="center">1</td><td width="20" align="center">1</td></tr> <tr><td width="20" align="center">1</td><td width="20" align="center">0</td><td width="20" align="center">1</td></tr> <tr><td width="20" align="center">0</td><td width="20" align="center">1</td><td width="20" align="center">0</td></tr><tr><td width="20" align="center">0</td><td width="20" align="center">0</td><td width="20" align="center">0</td></tr> </tbody></table>Для наглядности рассмотри еще один пример.
Применим операцию к двум числам - 6 и 12.
Их интерпертации в двоичной системе счисления:
6 - 0110
8 - 1100
______
|0110|
|1100|
|----|
|0100|
Получилось 0100 - 4.
Используется эта команда когда нужно выделить часть операнда, например таким образом вполне можно выделить первые 4 бита AH
AND AH,00001111h

Ivan_32
19.02.2009, 19:21
Команда OR - логическое ИЛИ для двух операндов, результат сохраняется в первом.
Семантика:
OR r8/r16/r32,m8/m16/m32
OR m8/m16/m32,r8/r16/r32
OR r8/r16/r32,r8/r16/r32
Для начала выясним что же такое логическое ИЛИ. В Дискретной математике эту операцию называют дизъюнкцией или логическим сложением.
В ассемблере эта операция работает с битами.
Таблица Истинности:
<table border="1" bordercolor="black" cellpadding="2" cellspacing="0"><tbody><tr><td width="20" align="center">OP1</td><td width="20" align="center">OP2</td><td width="20" align="center"> OR</td></tr><tr><td width="20" align="center">1</td><td width="20" align="center">1</td><td width="20" align="center">1</td></tr> <tr><td width="20" align="center">1</td><td width="20" align="center">0</td><td width="20" align="center">1</td></tr> <tr><td width="20" align="center">0</td><td width="20" align="center">1</td><td width="20" align="center">1</td></tr><tr><td width="20" align="center">0</td><td width="20" align="center">0</td><td width="20" align="center">0</td></tr> </tbody></table>Для наглядности рассмотри еще один пример.
Применим операцию к двум числам - 6 и 12.
Их интерпертации в двоичной системе счисления:
6 - 0110
8 - 1100
______
|0110|
|1100|
|----|
|1110|
Получилось 1110 - 14.
Эта команда используется когда нужно установить в операнде бит в состояние TRUE(1). Для примера:
OR AH,00100000b
Установит шестой бит в состояние TRUE(1).

Ivan_32
19.02.2009, 19:28
Команда XOR - логическое исключающее ИЛИ для двух операндов, результат сохраняется в первом.
Семантика:
XOR r8/r16/r32,m8/m16/m32
XOR m8/m16/m32,r8/r16/r32
XOR r8/r16/r32,r8/r16/r32
Для начала выясним что же такое логическое исключающее ИЛИ. В Дискретной математике эту операцию называют исключающим ИЛИ.
В ассемблере эта операция работает с битами.
Таблица Истинности:
Таблица Истинности:
<table width="121" border="1" bordercolor="black" cellpadding="2" cellspacing="0" height="170"><tbody><tr><td width="20" align="center">OP1</td><td width="20" align="center">OP2</td><td width="20" align="center">XOR
</td></tr><tr><td width="20" align="center">1</td><td width="20" align="center">1</td><td width="20" align="center">0
</td></tr> <tr><td width="20" align="center">1</td><td width="20" align="center">0</td><td width="20" align="center">1</td></tr> <tr><td width="20" align="center">0</td><td width="20" align="center">1</td><td width="20" align="center">1
</td></tr><tr><td width="20" align="center">0</td><td width="20" align="center">0</td><td width="20" align="center">0</td></tr> </tbody></table>
Для наглядности рассмотри еще один пример.
Применим операцию к двум числам - 6 и 12.
Их интерпертации в двоичной системе счисления:
6 - 0110
8 - 1100
______
|0110|
|1100|
|----|
|1010|
Получилось 1010 - 14.
Эта команда - основа всех алгоритмов шифрования/хеширования.
Имеем шифрующий ключ - 00001000h
При зашифровании такая команда:
XOR AH,00001000h
Как ни странно но когда будем расшифровывать нужно применить одну и ту же команду:
XOR AH,00001000h
Удобство на лицо. Главное что бы этот самый ключ знали только вы и тот кто принимает сообщение.
Конечно такой метод шифрования довольно прост и криптостойкость у него мизерная. Но зато это самый быстрый вариант.
Все остальные основаны на нем.

Ivan_32
19.02.2009, 19:38
Команда NOT - логическое отрицание.
Семантика:
NOT r8/r16/r32
NOT m8/m16/m32
Для начала выясним что же такое логическое отрицание.
В ассемблере эта операция работает с битами.
Таблица Истинности:
<table border="1" bordercolor="black" cellpadding="2" cellspacing="0"><tbody><tr><td width="20" align="center">OP1</td><td width="20" align="center">OP2</td></tr><tr><td width="20" align="center">1</td><td width="20" align="center">0</td></tr> <tr><td width="20" align="center">0</td><td width="20" align="center">1</td></tr> </tbody></table>Для наглядности рассмотри еще один пример.
Применим операцию к числу 10
Его интерпертация в двоичной системе счисления:
10 - 1010
______
|1010|
|----|
|0101|
Получилось 0101 - 5.
Эта команда инвертирует все биты операнда. Иногда бывает очень полезно.

Ivan_32
19.02.2009, 19:46
Команда SHR побитовый сдвиг с лева на право в операнде.
Семантика:
SHR r8/r16/r32,r8/m8
SHR m8/m16/m32,r8/m8
Двигает биты в прямом смысле этого слова, после битов остаются нули.
Например есть число. 1000b
MOV AL,1000b
SHR AL,2
В результате в AL окажется число 0010b - бит подвинулся ровно на 2 позиции.
Таким образом можно выделить верхнии 4 бита AL:
SHR AL,4
Например было в AL число 11110000b, а станет 00001111b.

Команда SHL побитовый сдвиг с права на лево в операнде.
Семантика:
SHL r8/r16/r32,r8/m8
SHL m8/m16/m32,r8/m8
Двигает биты в прямом смысле этого слова, после битов остаются нули.
Например есть число. 1000b
MOV AL,0011b
SHL AL,2
В результате в AL окажется число 1100b - бит подвинулся ровно на 2 позиции.
Таким образом можно сохранить текущее значение AX, в E-части и продолжить работать с ним без опасений потри данных:
MOV EAX,FFFFh ;Это для наглядности.
SHL EAX,16
Такой вот финт ушами на самом деле очень неплохая оптимизация. Ведь этот сдвиг произойдет быстрее чем пересылка данных из AX в память. Хотя можно конечно и в другой регистр переслать.

Ivan_32
19.02.2009, 20:14
1. Биты в байте нумерованы с права на лево по возрастанию и начальный номер первого байта не один а ноль и каждый из них имеет свой вес.
Из весов всех установленных в TRUE(1) битов составляется число. Для пример вот число:
<table border="1" bordercolor="black" cellpadding="0" cellspacing="0"><tbody><tr><td align="center">Значение</td><td width="20" align="center">1</td><td width="20" align="center">0
</td><td width="20" align="center">1</td><td width="20" align="center">0
</td><td width="20" align="center">1</td><td width="20" align="center">1</td><td width="20" align="center">1</td><td width="20" align="center">0
</td></tr><tr><td align="center">Номер</td><td width="20" align="center">7
</td><td width="20" align="center">6
</td><td width="20" align="center">5
</td><td width="20" align="center">4
</td><td width="20" align="center">3
</td><td width="20" align="center">2
</td><td width="20" align="center">1</td><td width="20" align="center">0
</td></tr> <tr><td align="center">Вес</td><td width="20" align="center">128
</td><td width="20" align="center">64
</td><td width="20" align="center">32
</td><td width="20" align="center">16
</td><td width="20" align="center">8
</td><td width="20" align="center">4
</td><td width="20" align="center">2
</td><td width="20" align="center">1</td></tr> </tbody></table>7,5,3,2,1 - биты установлены в 1, посчитаем сумму весов этих битов:
128+32+8+4+2=174.

2. Для того что бы обратится к памяти по определенному адресу например 00010000h нужно поставить это число в квадратные скобки [].
Например:
MOV EAX,DWORD PTR[00010000h]
обратится к слову по адресу 00010000h
А вот:
MOV EAX,00010000h
Просто перешлет число 00010000h в EAX.

3. При некоторых операциях а особенно при тех в которых задействуется память, нужно преобразовывать операнд до размерности регистра.
Приставка PTR к операнду сделает это. Вместо [SIZE] нужно ставить DWORD , WORD ,BYTE или операнд нужно размерности, как показывает
практика операндов больше чем DWORD и операндов меньше чем BYTE в x86(32Bit) ассемблере не используется.
Для примера приведем:
MOV AL,BYTE PTR[EBX]
В качестве адресатора(переменная значение которой используется в качестве адреса) выступает EBX, размерность возвращаемого операцией [EBX] 4 байта, естественно в 1-байтовый AL они не поместятся, потому следующая строка в отличие от этой просто не скомпилируется.
MOV AL,[EBX]


4. [SIZE=2]Точка с запятой это символ однострочного комментария, многострочных в ассемблере вроде бы нет. То есть все что идет в строке за ; считается комментарием.

Ivan_32
19.02.2009, 20:53
5. Базовый каркас приложения для MASM:
.586
.model flat,stdcall
;Тут идут include-ы
;И includelib-ы
;А так же прототипы импортируемых функций
include "masm32.inc"
includelib "masm32.lib"
dwtoa proto :DWORD,:DWORD
;Сначала имя функции, потом слово proto, потом ТИП каждого ;аргумента через запятую.
.data
;инициализированные данные
;Задаются с помощью DB Define Byte DW Define Word
;DD Define DoubleWord
;DQ Define QuadWord
;и других типов данных.
;Так же можно автоматизировать повторяющиеся байты - var [размерность-db dw...] [Количество] dup([Значение])
;helloWorld db "Hello world",0
;Каждая строка должна заканчиватся нулевым символом.
WVal dw 1004
DVal dd 15050500
QVal dq 1000100010001000
AVal db 512 dup(0)
.data?
;зарезервированные данные
;Разница этого блока и .data в том что всем переменным здесь присваивается знак ?
WVal dw ?
DVal dd ?
QVal dq ?
AVal db 512 dup(?)
;ВАЖНО: имена переменных в этих двух блоках и во всех остальных не ;должны повторятся, тоесть текущий код неработоспособен.
.const
;константы задаются так же как переменные только они не компилилруются а заменяются при компиляции.
;Задаются они одной командой - equ.
CVal equ 1001
.code
start: ;Метка начала кода, имя можно использовать любое, главное что бы она была.
invoke ExitProcess,0 ; invoke - макрос вызова функции. Без этой функции программа будет как бы некорректно завершатся,
;это ничем не черевато. Просто ОС будет об этом оповещать.
end start ; это тоже обязательно.

6. Вместо виртуальных адресов в коде, используются метки. Метка задается в любом месте кода и указывается на адрес по которому начинается следущая за меткой команда, для задания метки пишется ее название и за названием двоеточие : Пример использования метки:
mov eax,0
Label: mov edx,0

Метка Label будет содержать адрес именно этой команды, mov edx,0 и больше никакой. Метки можно так же использовать и в качестве адреса. например это код положит в EAX адрес на который указывает метка:
LEA EAX,Label

Ivan_32
26.02.2009, 06:49
Регистры процессора


1. Регистры общего назначения:
[32Bit]EAX - аккумулятор, обычно используется для хранения результатов и промежуточных данных вычислений.
<table width="200" border="1" cellpadding="0" cellspacing="0"><tbody><tr width="200" align="center"><td colspan="4">EAX</td></tr><tr align="center"><td colspan="2" rowspan="2" width="100">
</td><td colspan="2" width="100">AX</td></tr><tr align="center"><td width="50">AH</td><td width="50">AL</td></tr></tbody></table>
[32Bit]EBX - база, обычно используется для адресации в памяти.
<table width="200" border="1" cellpadding="0" cellspacing="0"><tbody><tr width="200" align="center"><td colspan="4">EBX</td></tr><tr align="center"><td colspan="2" rowspan="2" width="100">
</td><td colspan="2" width="100">BX</td></tr><tr align="center"><td width="50">BH</td><td width="50">BL</td></tr></tbody></table>
[32Bit]ECX - счетчик, обычно используется для организации циклов.
<table width="200" border="1" cellpadding="0" cellspacing="0"><tbody><tr width="200" align="center"><td colspan="4">ECX</td></tr><tr align="center"><td colspan="2" rowspan="2" width="100">
</td><td colspan="2" width="100">CX</td></tr><tr align="center"><td width="50">CH</td><td width="50">CL
</td></tr></tbody></table>
[32Bit]EDX - данные, обычно используется для хранения результатов и промежуточных данных и операций ввода/вывода.
Это условные обозначения, никаких ограничений на использование нет.
<table width="200" border="1" cellpadding="0" cellspacing="0"><tbody><tr width="200" align="center"><td colspan="4">EDX</td></tr><tr align="center"><td colspan="2" rowspan="2" width="100">
</td><td colspan="2" width="100">DX</td></tr><tr align="center"><td width="50">DH</td><td width="50">DL
</td></tr></tbody></table>

2. Идексные регистры:
[32Bit]ESI - индекс источника.
<table width="200" border="1" cellpadding="0" cellspacing="0"><tbody><tr width="200" align="center"><td colspan="4">ESI</td></tr><tr align="center"><td colspan="2" rowspan="2" width="100">
</td><td colspan="2" width="100">SI
</td></tr></tbody></table>
[32Bit]EDI - идндекс приемника.
<table width="200" border="1" cellpadding="0" cellspacing="0"><tbody><tr width="200" align="center"><td colspan="4">EDI</td></tr><tr align="center"><td colspan="2" rowspan="2" width="100">
</td><td colspan="2" width="100">DI
</td></tr></tbody></table>
[32Bit]EBP - используется для произвольного доступа к элементам стека.
<table width="200" border="1" cellpadding="0" cellspacing="0"><tbody><tr width="200" align="center"><td colspan="4">EBP</td></tr><tr align="center"><td colspan="2" rowspan="2" width="100">
</td><td colspan="2" width="100">BP
</td></tr></tbody></table>

3. Указательные регистры:
[32Bit]ESP - указывает на текущий элемент стека.
<table width="200" border="1" cellpadding="0" cellspacing="0"><tbody><tr width="200" align="center"><td colspan="4">ESP</td></tr><tr align="center"><td colspan="2" rowspan="2" width="100">
</td><td colspan="2" width="100">SP</td></tr></tbody></table>
[32Bit]EIP - указывает на следующую инструкцию в сегменте кода.
<table width="200" border="1" cellpadding="0" cellspacing="0"><tbody><tr width="200" align="center"><td colspan="4">EIP
</td></tr><tr align="center"><td colspan="2" rowspan="2" width="100">
</td><td colspan="2" width="100">IP</td></tr></tbody></table>

4. Сегментные регистры:
[16Bit]CS - сегмент кода.
[16Bit]DS - сегмент данных.
[16Bit]SS - сегмент стека.
[16Bit]ES - дополнительный сегмент. Используется в строковых операциях.
[16Bit]FS - дополнительный сегмент без спец. предназначения.
[16Bit]GS - дополнительный сегмент без спец. предназначения.

5.Регистр флагов EFLAGS.
Регистр флагов отдельная тема. Это 32-Битный регистр каждый бит в котором что то означает и играет роль в какой то из операций.
Почти все команды условных переходов зависят от регистра флагов, вернее они проверяют состояние этих флагов.

Мы рассмотрим лишь некоторые из них:

CF - флаг переноса после арифметической операции.
1 - произошел перенос из старшего бита результата в следующий бит(в такой ситуации это буквально сам CF).
0 - переноса не было.

ZF - флаг нуля.
1 - результат последней операции нулевой.
0 - результат последней операции не нулевой.

OF - флаг переполнения.
1 - произошло переполнение.
0 - переполнения не было.

DF - флаг направления в строковых операциях.
1 - направление от старших адресов к младшим.
0 - направление от младших адресов к старшим.

Ivan_32
26.02.2009, 07:32
Команда CMP - сравнение двух операндов, результат сохраняется в битах EFLAGS
Семантика:
CMP r8/r16/r32,m8/m16/m32
CMP m8/m16/m32,r8/r16/r32
CMP r8/r16/r32,r8/r16/r32
Команда сравнивает два операнда вычитая из второго первый и по результатам сравнения выставляет флаги.
Допустим в EAX находится числов 0FFFFh тогда команда:
CMP EAX,0FFFFh
установит ZF в 0 - отличий не найдено.



Команда TEST - тестирует биты операнда 1 по маске в операнде 2.
Семантика:
TEST r8/r16/r32,m8/m16/m32
TEST m8/m16/m32,r8/r16/r32
TEST r8/r16/r32,r8/r16/r32
Команда тестирует биты первого операнда по маске во втором операнде:
TEST EAX,1000b
проверит установлен ли бит #3 в состояние TRUE(1) если да то ZF будет установлен в 1.
Сравнение битов кроме тех которые в маске(второй операнд) установлены в 1 не происходит.

Ivan_32
26.02.2009, 07:46
Команда JMP - безусловный переход.
Семантика:
JMP r32/m32
Передает управление коду по адресу в операнде.
JMP 00010000h
Передаст управление коду по адресу 00010000h
Фактически команда помещает в EIP значение 00010000h.

Команда JE - переход если равно.
Семантика:
JE r32/m32
Передает управление коду по адресу в операнде
если ZF=0.
CMP EAX,10h
JE 00010000h
Управление будет передано только если число в EAX равно 10h

Команда JNE - переход если не равно.
Семантика:
JNE r32/m32
Передает управление коду по адресу в операнде
если ZF=0.
CMP EAX,10h
JNE 00010000h
Управление будет передано только если число в EAX не равно 10h

Ivan_32
26.02.2009, 08:36
Команда PUSH - пересылка слова или двойного слова в стек.
Семантика:
PUSH r8/r16/r32
PUSH m8/m16/m32
Помещает слово или двойное слово из операнда в стек. Минимальный размер операнда - 2 байта.
Если операнд занимает 1 байт - в стек будет помещен этот байт а недостающий байт будет взят за нули.
PUSH 0FFh
Поместит с стек слово 00FFh
PUSH 0FFFFFFFFh
Поместит в стек двойное слово 0FFFFFFFFh
PUSH EAX
Поместит в стек содержимое регистра EAX.
PUSH AX
Поместит в стек содержимое регистра AX.
PUSH AH
Помсетстит в стек содержимео регистра AH дополненое до слова. То есть, если в AH содержится 0FFh
то в стек попадет 0FFh.
Данная команда не изменяет содержимое операндов.

Команда POP - пересылка данных из стека в операнд приемник.
Семантика:
POP r8/r16/r32
POP m8/m16/m32
Помещает байт\слово\двойное слово из стека в операнд приемник.
POP AL
Поместит байт из стека в AL , байт из стека будет стерт
POP AX
Поместит слово из стека в AX , слово из стека будет стерто
POP EAX
Поместит двойное слово из стека в EAX , двойное слово из стека будет стерто
POP BYTEVar
Поместит байт из стека в однобайтовую переменную BYTEVar
, байт из стека будет стерт.
POP WORDVar
Поместит байт из стека в двухбайтовую переменную WORDVar
, двойное слово из стека будет стерто.
POP DWORDVar
Поместит байт из стека в четырехбайтовую переменную DWORDVar
, двойное слово из стека будет стерто.

Ivan_32
28.02.2009, 06:53
Команда JG - переход если больше.
Семантика:
JG r32/m32
Передает управление коду по адресу в операнде
если первый операнд больше второго операнда, в последнем сравнении.
CMP EAX,10h
JG 00010000h
Управление будет передано только если число в EAX будет больше 10h.
Прим: Сравнение должно происходить с числами со знаком.

Команда JNG - переход если не больше.
Семантика:
JNG r32/m32
Передает управление коду по адресу в операнде
если первый операнд не больше второго операнда, в последнем сравнении.
CMP EAX,10h
JNG 00010000h
Управление будет передано только если число в EAX будет не больше 10h.
Прим: Сравнение должно происходить с числами со знаком.

Команда JL - переход если меньше.
Семантика:
JL r32/m32
Передает управление коду по адресу в операнде
если первый операнд меньше второго операнда, в последнем сравнении.
CMP EAX,10h
JL 00010000h
Управление будет передано только если число в EAX будет меньше 10h.
Прим: Сравнение должно происходить с числами со знаком.

Команда JNL - переход если не меньше.
Семантика:
JNL r32/m32
Передает управление коду по адресу в операнде
если первый операнд больше второго операнда, в последнем сравнении.
CMP EAX,10h
JNL 00010000h
Управление будет передано только если число в EAX будет не меньше 10h.
Прим: Сравнение должно происходить с числами со знаком.

Ivan_32
28.02.2009, 07:13
Команда JA - переход если больше.
Семантика:
JA r32/m32
Передает управление коду по адресу в операнде
если первый операнд больше второго операнда, в последнем сравнении.
CMP EAX,10h
JA 00010000h
Управление будет передано только если число в EAX будет больше 10h.
Прим: Сравнение должно происходить с числами без знака.

Команда JNA - переход если не больше.
Семантика:
JNA r32/m32
Передает управление коду по адресу в операнде
если первый операнд не больше второго операнда, в последнем сравнении.
CMP EAX,10h
JNA 00010000h
Управление будет передано только если число в EAX будет не больше 10h.
Прим: Сравнение должно происходить с числами без знака.

Команда JB - переход если меньше.
Семантика:
JB r32/m32
Передает управление коду по адресу в операнде
если первый операнд меньше второго операнда, в последнем сравнении.
CMP EAX,10h
JB 00010000h
Управление будет передано только если число в EAX будет меньше 10h.
Прим: Сравнение должно происходить с числами без знака.

Команда JNB - переход если не меньше.
Семантика:
JNB r32/m32
Передает управление коду по адресу в операнде
если первый операнд больше второго операнда, в последнем сравнении.
CMP EAX,10h
JNB 00010000h
Управление будет передано только если число в EAX будет не меньше 10h.
Прим: Сравнение должно происходить с числами без знака.

Ivan_32
28.02.2009, 07:52
Команда JNAE - переход если не больше и не равно.
Семантика:
JNAE r32/m32
Передает управление коду по адресу в операнде
если первый операнд больше или равен второму операнду, в последнем сравнении.
CMP EAX,10h
JNAE 00010000h
Управление будет передано только если число в EAX будет не больше и не равно 10h.
Прим: Сравнение должно происходить с числами без знака.

Команда JNBE - переход если не меньше или равно.
Семантика:
JNBE r32/m32
Передает управление коду по адресу в операнде
если первый операнд не больше и не равно второму операнду, в последнем сравнении.
CMP EAX,10h
JNBE 00010000h
Управление будет передано только если число в EAX будет не меньше и не равно 10h.
Прим: Сравнение должно происходить с числами без знака.


Команда JNLE - переход если не меньше и не равно.
Семантика:
JNLE r32/m32
Передает управление коду по адресу в операнде
если первый операнд не меньше не равен второму операнду, в последнем сравнении.
CMP EAX,10h
JNLE 00010000h
Управление будет передано только если число в EAX будет не меньше и не равно 10h.
Прим: Сравнение должно происходить с числами со знаком.


Команда JNGE - переход если не больше и не равно
Семантика:
JNGE r32/m32
Передает управление коду по адресу в операнде
если первый операнд не больше и не равен второму операнду, в последнем сравнении.
CMP EAX,10h
JNGE 00010000h
Управление будет передано только если число в EAX будет не больше и не равно 10h.
Прим: Сравнение должно происходить с числами со знаком.

Ivan_32
28.02.2009, 07:57
Команда JCXZ - переход если ECX==0
Семантика:
JCXZ r32/m32
Передает управление коду по адресу в операнде
если ECX==0
MOV ECX,20h
cycle:
MOV EAX,[DDVar+ECX]
DEC ECX
JCXZ cEND
JMP cycle
cEND:
Вот простой цикл на 20h итераций с использованием этой команды.
Также может быть например такая ситуация:
MOV EAX,[Var] ; Число которое сравнивают с нужным
MOV ECX,[DesVar] ; Число с которым будут сравнивать
SUB ECX,EAX
JCXZ DesAddr ;Если число оказалось равным, нужному - переход на адрес DesAddr.

Команда RET - возврат из подпрограммы(процедуры/функции)
Семантика:
RET
Адрес возврата берется из стека.
Команда можно интерпретировать так:
POP EAX
JMP EAX

Команда CALL - вызов подпрограммы(процедуры/функции)
Семантика:
CALL ProcName/ProcAddr/m32/r32
Команду можно интерпретировать так:
PUSH EIP
JMP ProcName/ProcAddr

Ivan_32
28.02.2009, 16:54
Команда JS - переход если результат последней
арифметической операции отрицательный
Семантика:
JS r32/m32
Передает управление коду по адресу в операнде
если реузльтат последней арифметической операции отрицательный. Иными словами если SF=1.
MOV EAX,10h
SUB EAX,20h
JS 00010000h
При такой последовательности команд управление будет передано коду по адресу 10000h

Команда JNS - переход если результат последней
арифметической операции не отрицательный.
Семантика:
JNS r32/m32
Передает управление коду по адресу в операнде
если реузльтат последней арифметической операции не отрицательный. Иными словами если SF=0.
MOV EAX,10h
ADD EAX,20h
JNS 00010000h
При такой последовательности команд управление будет передано коду по адресу 10000h

Ivan_32
09.03.2009, 05:16
Основные конструкции кода:

Конструкция IF
Пример:
cmp eax,0
jne lab
;тут расположен код который выполнится если eax==0
lab:

Конструкция IF ELSE
Пример:
cmp eax,0
je lab
;Тут находятся инструкции которые должны выполнится если eax==0
jmp labEnd ;этот переход сделан что бы не началось выполнение кода после метки lab.
lab:
;А тут инструкции которые должны выполнится если eax!=0
labEnd:
;Это точка выхода из данной конструкции.

Конструкция WHILE
Пример:
mov ecx,100
cycle:
;Тело цикла
dec ecx
cmp ecx,0
jne cycle

Ivan_32
09.03.2009, 05:31
Процедура перевода бинарных данных в HexText.
buff0 - двойное слово DWORD. Адрес буфера источника.
buff1 - двойное слово DWORD. Адрес буфера применика.
bLen - двойное слово DWORD. Количество переводимых данных(в байтах).
Требования к аргументам:
1. buff0 и buff1 должны быть двойными словами, в которых находятся адреса выделенной памяти.
2. Обьем выделнной для второго буфера памяти должен быть в 2 раза больше чем для первого.

proc _Hex2Text buff0,buff1,bLen
pushad
xor eax,eax
xor ebx,ebx
xor ecx,ecx
xor edx,edx
aCycle:
xor eax,eax
pushad
mov ebx,[buff0]
mov ah,byte[ebx+ecx]
;----------------->
shr ah,4
cmp ah,9
ja charA
add ah,30h
jmp endA
charA:
add ah,37h
endA:
;----------------->
mov ebx,[buff1]
mov byte[ebx+edx],ah
;==================>
mov ebx,[buff0]
mov ah,byte[ebx+ecx]
;----------------->
and ah,00001111b
cmp ah,9
ja charB
add ah,30h
jmp endB
charB:
add ah,37h
endB:
;----------------->
mov ebx,[buff1]
mov byte[ebx+edx+1],ah
popad
inc ecx
inc edx
inc edx
cmp ecx,[bLen]
jne aCycle
popad
ret
endp

Ivan_32
22.04.2009, 13:22
Команда SLD - установка флага направления DF
Семантика:
SLD
Команда SLD устанавливает флаг DF в состояние 1.
Пример:
SLD
После выполнения этой команды флаг DF будет установлен в состояние 1, что повлияет на работу
команд серий MOVSx STOSx и LODSx.

Команда СLD - снятие флага направления DF
Семантика:
СLD
Команда СLD устанавливает флаг DF в состояние 0.
Пример:
CLD
После выполнения этой команды флаг DF будет установлен в состояние 0, что повлияет на работу
команд серий MOVSx STOSx и LODSx.

Ivan_32
22.04.2009, 13:29
Команды LODSB/LODSW/LODSD - пересылка данных
Семантика:
LODSB
LODSW
LODSD
Команды загружают значение из памяти по адресу, который хранится в регистре ESI, регистры
AL(LODSB), AX(LODSW), EAX(LODSD) соответственно. При выполнении команды, значение в ESI инкрементируется или декрементируется
в зависимости от значение флага DF=Direction Flag. Если DF=0 то ESI будет декрементироватся каждый раз при выполнении команды LODSx
(х = B/W/D).

Аналоги на основе MOV:

LODSB:
MOV AL,BYTE[ESI]
if(DF=0)
{
ADD ESI,1
}
else
{
SUB ESI,1
}

LODSW:
MOV AX,WORD[ESI]
if(DF=0)
{
ADD ESI,2
}
else
{
SUB ESI,2
}

LODSD:
MOV EAX,DWORD[ESI]
if(DF=0)
{
ADD ESI,4
}
else
{
SUB ESI,4
}

Пример использования:
MOV ESI,szString
LODSB ;В AL сейчас находится первый байт строки.

MOV ESI,szString
LODSB ;В AX сейчас находится первое слово строки.

MOV ESI,szString
LODSB ;В EAX сейчас находится первое двойное слово строки.

Ivan_32
22.04.2009, 13:59
Команды STOSB/STOSW/STOSD - загрузка данных в память
Семантика:
STOSB
STOSW
STOSD
Команды загружают значения которые находятся соответственно в AL(STOSB),AX(STOSW),EAX(STOSD) в память по адресу, который находится в EDI.
При выполнении команды, значение в EDI инкрементируется или декрементируется
в зависимости от значение флага DF=Direction Flag. Если DF=0 то EDI будет декрементироватся каждый раз при выполнении команды STOSx

Аналоги на основе MOV:
STOSB:
MOV BYTE[EDI],AL
if(DF=0)
{
ADD EDI,1
}
else
{
SUB EDI,1
}

STOSW:
MOV WORD[EDI],AX
if(DF=0)
{
ADD EDI,2
}
else
{
SUB EDI,2
}

STOSD:
MOV DWORD[EDI],EAX
if(DF=0)
{
ADD EDI,4
}
else
{
SUB EDI,4
}

Пример использования:
MOV EDI,szString
STOSB ;В памяти по адресу EDI находится байт взятый из AL
MOV EDI,szString
STOSW ;В памяти по адресу EDI находится слово взятое из AX
MOV EDI,szString
STOSD ;В памяти по адресу EDI находится двойное слово взятое из EAX

Ivan_32
22.04.2009, 14:36
Команды SCASB/SCASW/SCASD - сравнение данных
Семантика:
SCASB
SCASW
SCASD
Команды сравнивают значение в регистре AL(SCASB),AX(SCASW),EAX(SCASD) соответственно с значением находящимся в памяти по адресу в регистре EDI. Команды аналогичны команде CMP.
При выполнении команды, значение в EDI инкрементируется или декрементируется
в зависимости от значение флага DF=Direction Flag. Если DF=0 то EDI будет декрементироватся каждый раз при выполнении команды SCASx

Аналоги на основе CMP:

SCASB:
CMP AL,BYTE[EDI]
if(DF=0)
{
ADD EDI,1
}
else
{
SUB EDI,1
}

SCASW:
CMP AX,WORD[EDI]
if(DF=0)
{
ADD EDI,2
}
else
{
SUB EDI,2
}

SCASD:
CMP EAX,DWORD[EDI]
if(DF=0)
{
ADD EDI,4
}
else
{
SUB EDI,4
}

Пример использования:
MOV EDI,szString
SCASB ;Сравнивается AL с байтом по адресу EDI
MOV EDI,szString
SCASW ;Сравнивается AX с словом по адресу EDI
MOV EDI,szString
SCASD ;Сравнивается EAX с двойным словом по адресу EDI

Ivan_32
22.04.2009, 15:12
Команды MOVSB/MOVSW/MOVSD - пересылка данных
Семантика:
MOVSB
MOVSW
MOVSD
Команды пересылают Байт,слово и двойное слово соответсвенно из памяти по адресу ESI в память по адресу EDI.
В зависимости от значения флага DF, ESI и EDI либо инкрементируются после выполнения команды(DF=0) или же декрементируются(DF=1).

Аналоги на основе MOV:

MOVSB:
MOV AL,BYTE[ESI]
MOV BYTE[EDI],AL
if(DF=0)
{
ADD EDI,1
ADD ESI,1
}
else
{
SUB ESI,1
SUB EDI,1
}

MOVSW:
MOV AX,WORD[ESI]
MOV WORD[EDI],AX
if(DF=0)
{
ADD EDI,2
ADD ESI,2
}
else
{
SUB ESI,2
SUB EDI,2
}

MOVSD:
MOV EAX,DWORD[ESI]
MOV DWORD[EDI],EAX
if(DF=0)
{
ADD EDI,4
ADD ESI,4
}
else
{
SUB ESI,4
SUB EDI,4
}

Пример использования:
MOV ESI,szStr0
MOV EDI,szStr1
MOVSB ;Пересылается байт из szStr0 в szStr1

MOV ESI,szStr0
MOV EDI,szStr1
MOVSW ;Пересылается слово из szStr0 в szStr1

MOV ESI,szStr0
MOV EDI,szStr1
MOVSD ;Пересылается двойное слово из szStr0 в szStr1

Ivan_32
22.04.2009, 15:18
Команды CMPSB/CMPSW/CMPSD - сравнение данных
Семантика:
CMPSB
CMPSW
CMPSD
Команды сравнивают байты, слова или двойные слова соотвественно по адресам в ESI и EDI соотвественно.
В зависимости от значения флага DF, ESI и EDI либо инкрементируются после выполнения команды(DF=0) или же декрементируются(DF=1).

Аналоги на основе CMP:

CMPSB:
MOV AL,BYTE[ESI]
CMP BYTE[EDI],AL
if(DF=0)
{
ADD EDI,1
ADD ESI,1
}
else
{
SUB ESI,1
SUB EDI,1
}

CMPSW:
MOV AX,WORD[ESI]
CMP WORD[EDI],AX
if(DF=0)
{
ADD EDI,2
ADD ESI,2
}
else
{
SUB ESI,2
SUB EDI,2
}

CMPSD:
MOV EAX,DWORD[ESI]
CMP DWORD[EDI],EAX
if(DF=0)
{
ADD EDI,4
ADD ESI,4
}
else
{
SUB ESI,4
SUB EDI,4
}

Пример использования:
MOV ESI,szStr0
MOV EDI,szStr1
CMPSB ;Сравнивается байт из szStr0 c байтом в szStr1

MOV ESI,szStr0
MOV EDI,szStr1
CMPSW ;Сравнивается слово из szStr0 c словом в szStr1

MOV ESI,szStr0
MOV EDI,szStr1
CMPSD ;Сравнивается двойное слово из szStr0 c двойным словом в szStr1

Ivan_32
23.04.2009, 09:00
Префикс REP - безусловный повтор команды
Семантика:
REP commmand
Префикс повторяет команду заданное количество итерация, это число хранится в ECX.
Пример использования:
CLD
MOV ESI,szSourceString
MOV EDI,szDestinationString
MOV ECX,10
REP MOVSB
На данном участке кода, из памяти по адресу szSourceString, переписываются 10 байт, в память по адресу szDestinationString.
Данный префикс удобен для циклического копирования данных(как и показано в примере). Так же можно посмотреть такой пример:
CLD
MOV AL,0
MOV EDI,pMem
MOV ECX,1000h
REP STOSB
Данный код заполняет 1000h байт по адресу pMem, значениями из AL.


Префикс REPE - условный повтор команды пока флаг ZF=1
Семантика:
REPE command
Префикс повторяет команду, до тех пор пока, ZF=1 или проще говоря, до тех пор пока результат последнего сравнения положительный - до тех пор пока равно.
В ECX содержится максимальное количество итераций.
Пример:
CLD
MOV EDI,szStr
MOV AL,'A'
MOv ECX,0FFFFFFFFh
REPE SCASB
SUB EDI,szStr
После выполнения кода в EDI будет записано количество подряд идущих букв 'A' в памяти по адресу szStr.
Тоесть, если допустим в памяти по этом адресу содержится такие значение "AAAAAFGAAA" то код прочтет первые 5 букв 'A' и прекратит выполнение.
Так как ZF после следущего сравнения установится в 0.

Префикс REPNE - условный повтор команды пока флаг ZF=0
Семантика:
REPNE command
Префикс повторяет команду, до тех пор пока, ZF=0 или проще говоря до тех пор пока не равно.
В ECX содержится максимальное количество итераций.
Пример:
CLD
MOV EDI,szStr
MOV AL,'F'
MOV ECX,0FFFFFFFFh
REPNE SCASB
Данный код найдет в памяти по адресу szStr символ 'F', в EDI будет содержатся его адрес.

Ivan_32
25.04.2009, 23:29
Команда LOOP - повтор блока команд без условий
Семантика:
LOOP Addres
Команда повторят блок команд с адреса в аргументе, до текущего адреса, ECX - раз.
Пример:
MOV ECX,10
looper:
MOV BYTE[EDX+ECX],AH
ADD EDX,1000h
LOOP looper
Данный код повторит блок инструкций 10 раз с метки looper по адрес команды.


Команда LOOPE - повтор блока команд пока равно
Семантика:
LOOPNE Addres
Команда повторят блок команд с адреса в аргументе, до текущего адреса, ECX - раз, пока ZF=1 или пока равно.
Пример:
MOV ECX,100
MOV ESI,szStr0
MOV EDI,szStr1
looper:
MOV AH,byte[ESI]
MOV AL,byte[EDI]
CMP AH,AL
LOOPE looper
Данный код повторит блок инструкций 100 раз с метки looper по адрес команды, но только пока ZF=1
Цикл поелезн когда нужно определить длину последовательности одинаковых байт в памяти.

Команда LOOPNE - повтор блока команд пока не равно
Семантика:
LOOPE Addres
Команда повторят блок команд с адреса в аргументе, до текущего адреса, ECX - раз, пока ZF=0 или пока не равно.
Пример:
MOV ECX,100
MOV ESI,szStr0
MOV EDI,szStr1
looper:
MOV AH,byte[ESI]
MOV AL,byte[EDI]
CMP AH,AL
LOOPNE looper
Данный код повторит блок инструкций 100 раз с метки looper по адрес команды, но только пока ZF=0.
Цикл полезен когда нужно найти байт в памяти.

Ivan_32
26.04.2009, 00:31
Команда PUSHAD - сохранить все основные регистры в стеке
Семантика:
PUSHAD
Сохраняет регистры ESI EDI EBP EBX EDX ECX EAX в стеке(именно в таком порядке)
Пример:
PUSHAD
POP [reg.EAX]
POP [reg.ECX]
POP [reg.EDX]
POP [reg.EBX]
POP [reg.NULL]
POP [reg.EBP]
POP [reg.EDI]
POP [reg.ESI]
Данный код сохранит все регистры общего назначение(они приведены выше) в импровизированную структуру reg.
Дабы не возникало вопросов что и как, приведу примерный вид этой структуры.
struc REGISTERS
{
.EAX dd ?
.ECX dd ?
.EDX dd ?
.EBX dd ?
.NULL dd ?
.EBP dd ?
.EDI dd ?
.ESI dd ?
}
Примечание:
Между ESI EDI EBP и EBX EDX ECX EAX выполнении команды загружается двойное слово - оно нулевое, в данном случае NULL
это ненужная переменая значение которой можно сбросить, иначе говоря это просто что бы пропустить это двойное слово.


Команда POPAD - выгрузить из стека все регистры основного назначения
Семантика:
POPAD
Выгружает из данные из стека в регистры EAX EDI EBP EBX EDX ECX EAX (именно в таком порядке).
Пример:
CLD
MOV ECX,8
MOV ESI,reg
MOV EDI,ESP
REP MOVSB
POPAD
Загружаем в память содержимое структуры REGISTERS и вытаскиваем это из стека командой POPAD

Ivan_64
11.12.2009, 07:39
Кстати по поводу pushad-ов и popad-ов. Они далеко не восстанавливают равновесие в самом стеке, потому при вхождении в нестабильную секцию(где есть функции которые могут оставить в стеке что то свое - например входные параметры) лучше сохранить ESP в какой ни будь переменной и восстановить в конце процедуры.
Для примера:
proc TestFunc
mov dword[oldESP],esp
pushad
;А здесь код.
popad
mov esp,dword[oldESP]
ret
endp