> For the complete documentation index, see [llms.txt](https://backoftut.gitbook.io/intro-cracking-with-ollydbg/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://backoftut.gitbook.io/intro-cracking-with-ollydbg/ch-05.md).

# Глава 5

## МАТЕМАТИЧЕСКИЕ ИНСТРУКЦИИ

### INC И DEC

Эти инструкции увеличивают или уменьшают значение операнда, прибавляя к нему один в случае с INC или, соответственно, отнимая один в случае с DEC.

Идём в Олли и, как обычно, открываем крэкми CrueHead'а [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/blob/master/.gitbook/assets/files/1/ollydbg01-Crackme.7z) и в первой строке пишем:

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-04522e01c098a4d8ad1f0c21bc2254d18cc62c17%2F1.png?alt=media)

На моей машине EAX изначально равен нулю. Если у вас это не так, вы можете изменить это вручную.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-edcdbe068e1316d31aaf7ba5c82129b67240e2ab%2F2.png?alt=media)

Затем нажимаем F7 и выполняем инструкцию INC EAX, увеличивая его на один.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-41f50a1962d4034b54524abb509acf08d9e66407%2F3.png?alt=media)

Таким же образом можем ввести DEC сразу под предыдущей инструкцией.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-209b9e76a834ed8e78c0459c39677613db62d160%2F4.png?alt=media)

Нажимаем F7 и выполняем инструкцию DEC EAX, которая уменьшает значение регистра на 1, после чего он принимает предыдущее значение - 0.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-9ba8c464010914620108bb4beed4127df6522a73%2F5.png?alt=media)

Также можно увеличивать или уменьшать значение ячейки памяти.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-fd3813f8a92833d185aa6c18f2f4fa8690adc4be%2F6.png?alt=media)

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

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-ea5d31728948d53c8b60c47f7de2d28087263c65%2F7.png?alt=media)

Что было бы, если бы у секции было выставлено разрешение на запись? Идём в DUMP по адресу 405000.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-763fe1988f11c088d8519c6889ac167fd02783b2%2F8.png?alt=media)

Содержимое, если его прочитать наоборот, будет равно 00001000, значит, если бы оно было увеличено, то было бы 00001001

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-733704df9395f72eae2a71d06a86131d8f4cef65%2F9.png?alt=media)

В данном случае для DWORD прибавление 1 производилось к 4 байтам содержимого.

Для WORD суммирование будет применено только к двум последним байтам.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-6aebd3a4dfa16d8110d49e1edd9e3200a4d5114e%2F10.png?alt=media)

И при BYTE суммирование будет применено только к последнему байту.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-d68605446da95a26707720e63538b8f15414e0a9%2F11.png?alt=media)

### ADD

ADD, как можно видеть, суммирует оба операнда, сохраняя результат в первом.

ADD EAX, 1 похоже на INC EAX.

Также можем складывать регистры.

Идём в Олли.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-286a313cc544df7dac57f493ae7310a450a466ea%2F12.png?alt=media)

До выполнения инструкции:

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-93b79452b5b49f726d151d5adfdb8effb5c8d76b%2F13.png?alt=media)

На моей машине EAX содержит 00000000, а ECX - 12FFB0. У вас данные регистры могут содержать другие значения, также вы можете, если хотите, их изменить, но когда вы нажмёте F7, оба значения будут сложены, а результат помещён в EAX. Смотрим:

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-71190dac80b14c1eecacd05bd8ac8e899fcf0ada%2F14.png?alt=media)

Здесь EAX стал красного цвета, потому что он был модифицирован и содержит результат суммирования.

Также можем сложить регистр с содержимым ячейки памяти.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-60e55f742b13ffa8d66d3710e5fe86263e5a0260%2F15.png?alt=media)

В данном случае нет проблем с правами на запись, так как меняется и сохраняет результат регистр EAX, а содержимое \[405000] остаётся неизменным. Соответственно, не генерится и никакого исключения.

До нажатия F7 видим, что EAX содержит 0, а по адресу 405000 находится значение 00001000.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-5bae2d70087cad63ab4be5513cf44f1ae2394a0b%2F16.png?alt=media)

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-6d91eaf44c5f488bb956904f52ae12f3eaa8f06e%2F17.png?alt=media)

Нажимаем F7, после чего вычисляется сумма.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-73dbb35eac49033fe39e85466aab58ecf7bb4451%2F18.png?alt=media)

Так как EAX = 0, то в EAX сохраняется результат, равный 1000.

Если хотим, чтобы результат сохранился в памяти, то пишем:

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-b53e1c7852a3a9cb456444a7ef4ed3e0313a2083%2F19.png?alt=media)

В этом случае результат сохранится в 405000, и так как это модифицирует память, то в нашем случае при нажатии на F7 будет сгенерировано исключение об отсутствии прав на запись.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-e849d5e28e4bb57da4a21f955524d2fce35a2a09%2F20.png?alt=media)

### ADC (ADD С ПЕРЕНОСОМ)

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

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-0783c67596a4bb38b9a1e324ee33dfa4fe770bff%2F21.png?alt=media)

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-f58e9d3db3eeb490fa7a795aae61b8fc66e7a518%2F22.png?alt=media)

Здесь видим, что здесь будет суммирован EDX, содержащий 21, с числом 3, а также вычислен флаг C, который сейчас равен нулю. Нажимаем F7.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-cb2d429e2ccf809bd3b86ea048513c88ee44b861%2F23.png?alt=media)

Видим, что результат равен 24. Теперь повторим эту операцию, но с флагом C равным 1, значение которого мы можем изменить, если дважды кликнем по нему мышью.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-c80e48b39c09461998f927040363e4400922b403%2F24.png?alt=media)

Сделав это, повторяем выполнение инструкции, изменив значение флага C.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-c640b8968b840b218444331b3670cfe9523b2086%2F25.png?alt=media)

Нажимем F7 и вуаля - результат равен 25.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-ddd24fd5e4917c179ab8e97569a195158e37549a%2F26.png?alt=media)

Так как сумма EDX (21) с 3 и флагом C, равном 1, равна 25.

### SUB

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

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-d836d7e1db7718d7a7dd2bbbddb9970b078aef82%2F27.png?alt=media)

На моей машине регистры до выполнения инструкции содержали следующее:

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-00d249aefba6c535561ea9c9291b9c6bb734c109%2F28.png?alt=media)

По нажатию F7 инструкция вычтет от EAX, который содержит ноль, значение 2.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-3b2e1ada2bde614a72fd19af08e762dfe404d925%2F29.png?alt=media)

Результатом является -2, что в шестнадцатеричной системе выглядит как FFFFFFFE, в чём мы можем убедиться, если кликнем два раза мышью на данном значении:

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-be69eb4294021fd25bc043d20946f0cc71a83b57%2F30.png?alt=media)

Видим, что в десятеричной системе это равно -2.

Также можно отнимать значение регистров и ячеек памяти примерно таким же образом, как и при использовании инструкции ADD.

`SUB EAX, ECX`

То есть EAX-ECX с сохранением результата в EAX.

И

`SUB EAX,DWORD PTR DS:[405000]`

Вычитает от EAX содержимое ячейки памяти по адресу 405000, сохраняя результат в EAX.

Обратный случай:

`SUB DWORD PTR DS:[405000],EAX`

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

### SBB

Это операция является обратной к ADC: она вычисляет разность между операндами, отнимает от того, что получилось, значение флага переноса (флаг C) и сохраняется окончательный результат в первый операнд.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-e16c30a6ee737b442b391a8c9c568a9e524c3e08%2F31.png?alt=media)

До выполнения в EDX находилось 21, а флаг переноса был равен 0.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-9d27949cee2dfd4ac38bb196b411e40b8448ebce%2F32.png?alt=media)

Нажатие на F7 вычтет из EDX число 3, а затем ноль, которому равен флаг C.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-a38621ae174a97614c978651251409c51bb0b9f0%2F33.png?alt=media)

Теперь повторим операцию, присвоив флагу C значение 1.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-914d6c0edc49ba9167bf21d83352aa99746569e6%2F34.png?alt=media)

Нажимает на F7 и теперь из EDX вычитается 3, а затем единица, которой равен флаг C.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-eb5d306c7f8b33415622107d17ee7ca2a3c1ff3c%2F35.png?alt=media)

В данном случае результат равен 1D.

### MUL

Ок, есть две инструкции для выполнения умножения. Первой из них является MUL, которая не учитывает знаки чисел. Она использует только один операнд, а другим всегда является EAX Результат сохраняется в EDX:EAX.

Например:

`MUL ECX`

Здесь ECX умножается на EAX без учёта знаков их значений, а результат сохраняется в EDX:EAX.

Рассмотрим следующий пример с помощью OllyDbg:

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-fd80cb23470bc8f0e976d1e671d4917783f972db%2F36.png?alt=media)

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-dad459b5f48549e5cb784b91375b83baab2877d4%2F37.png?alt=media)

Поместим в EAX число FFFFFFF7, в ECX - 9, а затем посчитаем результат с помощью стандартного калькулятора Windows:

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-a3c6ab5f58b10f5c1559eed6543da7762a9f869b%2F38.png?alt=media)

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-e2cc6789ec65c9d5b7d2f0f2b61bf261724fa8ef%2F39.png?alt=media)

Получится:

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-69c836fc16325fc68331b934810ef99b7ec98a82%2F40.png?alt=media)

Это не поместится в EAX. Посмотрим, что будет в Олли и нажмём на F7.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-a7f348bab887eb1993a7c6f1248f9264109db212%2F41.png?alt=media)

EDX и EAX выделены красным, так как их значение было изменено, и, как видим, в EAX было сохранено то, что поместилось, а остальное в EDX. В данном случае 8-рка, которую не смог вместить EAX, попала в EDX, поэтому в таких случая говорят, что результат содержится в EDX:EAX, то есть два регистра используются как один двойного размера.

В случае с

`MUL DWORD PTR DS:[405000]`

Происходит умножение ячейки памяти по адресу 405000 на EAX, а результат, как обычно, помещается в EDX:EAX без учёта знаков операндов.

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

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-a7fc0ba6bfdb8e057765d0b022087a56e86b0e7e%2F42.png?alt=media)

Как можно видеть, во втором ряду находится значение со знаком (в данном случае FFFFFFAF это -81, если учитывать знак), но в таких операциях как MUL все числа считаются БЕЗЗНАКОВЫМИ. Третья строка как раз и содержит десятеричное значение без знака. Сейчас видим, что число FFFFFFAF - это 4294967215, если рассматривать его как положительное, то есть беззнаковое.

### IMUL

Инструкция IMUL - это умножение со знаком и употребляется аналогично MUL.

IMUL ECX

Данная операция производит умножение ECX на EAX, а результат сохраняется в EDX:EAX с учётом знака операндов.

Несмотря на сходство с предыдущей инструкцией, IMUL позволяет использовать больше одного операнда, что невозможно в случае с MUL.

Из туториала CAOS'а:

> Несмотря на использование регистров EAX и EDX по умолчанию, можно указать другие источники и приёмники данных вплоть до трёх операндов. Первый - место, куда необходимо поместить результат и которое всегда должно быть регистром, второй и третий - два значения, которые нужно перемножить. В этих примерах увидим применение этой инструкции с двумя или тремя операндами.
>
> `F7EB IMUL EBX EAX x EBX -> EDX:EAX`

Это первый пример, который похож на MUL, не считая того, что здесь учитываются знаки.

`696E74020080FF IMUL EBP, DWORD PTR [ESI+74],FF800002 [ESI+74] x FF800002 -> EBP`

Это второй пример, в котором три операнда: содержимое ESI+74 умножается на FF800002, а результат сохраняется в EBP. Мы можем посмотреть его в действии с помощью Олли.

Скопируем строку `IMUL EBP, DWORD PTR [ESI+74], FF800002` **в Олли**.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-c5c1b0b69c29137632046a3dc617c38003dde67b%2F43.png?alt=media)

Видим, что нажатие кнопки "ASSEMBLE" выдаёт ошибку. Это происходит из-за того, что в Олли к числам, которые начинаются с букв, нужно слева приписывать ноль. Исправляем:

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-84926ca2cb0f3da8d6a1a6700cef118b27ac8474%2F44.png?alt=media)

Теперь нажатие на ASSEMBLE проходит без ошибок.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-db0d404b2d4e0ac014308eec265f00faa4de7d70%2F45.png?alt=media)

Изменяем значение ESI на 401000, чтобы быть уверенными, что адрес ESI + 74, из которого будет происходить чтение, существует.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-596a4265fc1937aa695772e43818790081976761%2F46.png?alt=media)

Видим в пояснениях:

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-baeeabaee52fe9ba30bfe7d831f16ffbf8333ba1%2F47.png?alt=media)

Здесь говорится, что ESI + 74 - это адрес 401074, содержимым которого является C7000000. Идём в DUMP с помощью "GOTO EXPRESSION 401074".

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-fbe9b644d864912143532f3712e34dea3efd4a23%2F48.png?alt=media)

Это значение, которое, если прочитать его наоборот, равно C7000000, будет умножено на FF800002, а результат данной операции будет сохранён в EBP.

`IMUL EBP, DWORD PTR [ESI+74], FF800002`

Нажав F7, видим, что EBP стал красным, так как сейчас он содержит результат.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-07d36a56ec54b5ca68163888da2412830784ccd3%2F49.png?alt=media)

Калькулятор даёт нам следующий результат операции C7000000 \* FF800002:

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-3ee526ecb2df340d68e501fe8906181f9e082b3d%2F50.png?alt=media)

Но поскольку EBP не может вместить его полностью, то в нём остаётся только то, что поместилось, а остальное отбрасывается.

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

`0FAF55E8 IMUL EDX, DWORD PTR [EBP-18] EDX x [EBP-18] -> EDX`

Как видим, основной способ для умножения больших чисел - использовать IMUL только с одним операндом, так как в этом случае результат сохраняется в EDX:EAX, то есть он может быть двойного размера, чего нельзя добиться при использовании двух или трёх операндах, соответственно, данную возможность следует применять для маленьких чисел.

### DIV (Unsigned Divide) / IDIV (Signed Divide)

Это инструкции, обратные по отношении к MUL и IMUL соответственно.

DIV имеет только один операнд, не учитывает знаки и сохраняет результат в EDX:EAX.

IDIV всегда учитывает знаки. Если используется один операнд, то, как и DIV, сохраняет результат в EDX:EAX, в случае двух - делит один на другой и сохраняет результат в первый, а при трёх операндах делит второй на третий и сохраняет то, что получилось, в первый.

Не думаю, что нужно приводить здесь примеры, похожие на те, что были в разделе, посвящённом MUL и IMUL.

### XADD (Обменять и сложить)

Как можно догадаться, это смесь XCHG и ADD, то есть если :

`XADD EAX,ECX`

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-e2c270d40e33fead3a726724d87e2e52fb26d671%2F51.png?alt=media)

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-a8ba2c659c28cdcf132281f6fb1ab0732bc15f57%2F52.png?alt=media)

Видим, что ECX равен 1, а EAX - 9. По нажатию на F7 они обменяются значениям, т.е. в EAX попадёт 1, а в ECX - 9, после чего произойдёт сложение.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-b7e37593f924fd9225db28c7d36beb89a389ffad%2F53.png?alt=media)

Видно, что результат затем был сохранён в первый операнд. Регистр ECX содержит число 9, которое находилось до выполнения операции в EAX.

### NEG

Назначением данной инструкции является менять знак заданного числа на противоположный, т.е. если у нас есть число 32 в шестнадцатеричной системе, и мы применяем к ней NEG, то результатом будет его отрицательный аналог.

Пример:

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-b9bece9597ab94e4f623b01eca11005d76dc307e%2F54.png?alt=media)

Пишем в Олли NEG EAX и заносим в EAX число 32.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-e8821ddd9451bac61c20045e22dd34be43a7b65e%2F55.png?alt=media)

После нажатия на F7 в EAX окажется отрицательный вариант числа 32. Смотрим:

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-74fec1edc5b435385d0b34564bd52c8e2cc7a7a0%2F56.png?alt=media)

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-5e5501aa3209ec77297c81bac8a48f2b26825508%2F57.png?alt=media)

Во втором ряду видим, что результатом является -50 в десятеричной системе (это соответствует -32 в шестнадцатеричной).

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-430a8027dcb2989dafe4c7280c4875db2b73c92e%2F58.png?alt=media)

Если напечатаем в CommandBar'е число -32 в шестнадцатеричной системе, чтобы выяснить, чему оно равно в десятеричной, то получим ответ, что это значение эквивалентно -50, а также пояснение, что это FFFFFFCE.

Так что видим, что NEG меняет знак операнда на обратный.

## ЛОГИЧЕСКИЕ ИНСТРУКЦИИ

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

### AND

Результатом этой операции над двумя битам является 1, если они оба равны 1, и 0 во всех остальных случаях.

* 1 and 1 = 1
* 1 and 0 = 0
* 0 and 1 = 0
* 0 and 0 = 0

Посмотрим пример в OllyDbg:

`AND ECX,EAX`

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-ab27fc671cd567c9097a0480a2890b3ca841fbb7%2F59.png?alt=media)

Делаем ECX=00001200, а EAX=3500.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-87bd069279d1a5867d3e13765baf3aee64c15a90%2F60.png?alt=media)

Чтобы сделать эту операцию вручную, нужно перевести оба числа в двоичный вид:

* 1200 в двоичном виде будет равно 01001000000000
* 3500 в двоичном виде будет равно 11010100000000

Применим вышеприведённую таблицу операции AND побитно, например, к последней цифре:

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-c88582e4a9d79f19709a863e9eff5ff97420a755%2F61.png?alt=media)

Из двух нулей получится ноль. Повторим эту процедуру над всеми битами и получим 01000000000000, поскольку ситуация, когда оба биты равны 1 у нас встречается только один раз, а посему и в результате единица встретится тоже только один раз.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-f8e9076dba5e494b5a7b2dba58061ce8b7136c7a%2F62.png?alt=media)

Если нажмём F7 в Олли, то увидим, что в ECX находится результат 1000, что эквивалентно 01000000000000 в двоичном виде.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-642be1b8c08bc5bb5a11000031cdd46556f365b3%2F63.png?alt=media)

### OR

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

Получается 1, если один или оба бита равны 1, и 0 во всех остальных случаях.

* 1 or 1 = 1
* 1 or 0 = 1
* 0 or 1 = 1
* 0 or 0 = 0

### XOR

Здесь то же самое, только используем таблицу функции XOR.

Получается 1, если один и только один из двух битов равен 1, и 0 во всех остальных случаях.

* 1 xor 1 = 0
* 1 xor 0 = 1
* 0 xor 1 = 1
* 0 xor 0 = 0

### NOT

Просто инвертирует значение:

* not 1 = 0
* not 0 = 1

Пример: not 0110 = 1001

Если у нас, например, EAX=1200, что в двоичном виде равно 1001000000000, то все нули превратятся в 1, а все 1 в 0.

`00000000000000000001001000000000`

После применения NOT получим

`11111111111111111110110111111111`

что в калькуляторе Windows в шестнадцатеричном виде отобразится как FFFFEDFF.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-4ff29774977cfa48c49ecafab345bcb2a77e8e8e%2F64.png?alt=media)

В Олли до нажатия на F7 сделаем EAX равным 1200.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-28d1fff552791376a2ae2a62d972b863610c430c%2F65.png?alt=media)

Нажимаем F7.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-ef9eb6dc1045371b20a89a8331e55c3c8a018fa0%2F66.png?alt=media)

Видим, что результат тот же самый.

Ок, здесь мы закончим пятую часть "Введения...". Пока подумайте над тем, что узнали в этой главе, а нам ещё предстоит рассмотреть инструкции сравнения, выходов, call и ret.

Шаг за шагом дорога приведёт нас к цели.

\[C] Рикардо Нарваха, пер. Aquila
