# Глава 5

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

### INC И DEC

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

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTvyKsF7A_Rl7cHl0%2F1.png?generation=1566513554131539\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTvyeivScfLNnh2ok%2F2.png?generation=1566513556385833\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTvzP_PwrdEWLFnJb%2F3.png?generation=1566513554440194\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTvzvV3lXD_MY-jl6%2F4.png?generation=1566513588357749\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw-k0CMccX9JYJjf%2F5.png?generation=1566513621959540\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw01dnCmEpPgA5iQ%2F6.png?generation=1566513618473524\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw0g_8UZIZAM70w4%2F7.png?generation=1566513561163531\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw1R-XIwjnawYuLe%2F8.png?generation=1566513640364172\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw1eLIMuRrBjIIOB%2F9.png?generation=1566513601622926\&alt=media)

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

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw1qZ0xmmEjEUj-_%2F10.png?generation=1566513554739785\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw28Hkc2-M7vn6k8%2F11.png?generation=1566513554218704\&alt=media)

### ADD

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

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

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

Идём в Олли.

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw2LHM6v_1-mfO6i%2F12.png?generation=1566513554357311\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw2YrqUKKstM0AQP%2F13.png?generation=1566513561192389\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw2qdOM7nTFxW_eQ%2F14.png?generation=1566513555464713\&alt=media)

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

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw3DlkoJF5Ut_EZT%2F15.png?generation=1566513554067705\&alt=media)

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

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw3S5-n-k-1Pj_ZF%2F16.png?generation=1566513622206916\&alt=media)

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw3vQujev5fVp6jG%2F17.png?generation=1566513601217861\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw47uFMj8Pzpn_em%2F18.png?generation=1566513616384626\&alt=media)

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

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw4SvFFEQpFPtkEM%2F19.png?generation=1566513631483725\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw4iLw0mip_R_xdM%2F20.png?generation=1566513672043173\&alt=media)

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

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw4yHD3FcOJqM9-V%2F21.png?generation=1566513643212171\&alt=media)

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw59E5IPXhuv2lEt%2F22.png?generation=1566513635828660\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw5KjREzjegqSI2w%2F23.png?generation=1566513592790666\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw5W5Xy3MdsqDvng%2F24.png?generation=1566513561590082\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw5fgo0lw326y7Cm%2F25.png?generation=1566513555129579\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw5p3NHowaeZJFX8%2F26.png?generation=1566513554475946\&alt=media)

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

### SUB

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw603xANGNMCcBEi%2F27.png?generation=1566513609463334\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw6Bp0nCYfb89ukc%2F28.png?generation=1566513637594604\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw6LMa2v6hWjLEfC%2F29.png?generation=1566513593202900\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw6UIHWknabHtcK6%2F30.png?generation=1566513673445569\&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://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw6e0ro5yd_mC3Kf%2F31.png?generation=1566513589711359\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw6p-5p2fa_mbDfK%2F32.png?generation=1566513576428771\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw791b4prZNwXI3z%2F33.png?generation=1566513587430513\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw7V7WOswNYbBMTv%2F34.png?generation=1566513673360205\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw7qkzs60RZPsb81%2F35.png?generation=1566513561455238\&alt=media)

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

### MUL

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

Например:

`MUL ECX`

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

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw8FiqKOfi0X4eWG%2F36.png?generation=1566513583444780\&alt=media)

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw8V0JpLBpscR0zS%2F37.png?generation=1566513566112638\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw8iPYQQrfzEjIPO%2F38.png?generation=1566513639379397\&alt=media)

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw8scolT-dWsoNUZ%2F39.png?generation=1566513559328292\&alt=media)

Получится:

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw96UGy0hVWA3k6R%2F40.png?generation=1566513587032238\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw9EiPqzLKiGk1oS%2F41.png?generation=1566513586857711\&alt=media)

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

В случае с

`MUL DWORD PTR DS:[405000]`

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

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw9QP8fUp3gD-RAc%2F42.png?generation=1566513673767838\&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://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTw9ou2kOvlJkvQGj%2F43.png?generation=1566513631129867\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwA4zdcWANd3m8cw%2F44.png?generation=1566513639112897\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwASzlXx-r6ub6Py%2F45.png?generation=1566513599305417\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwAuJBY-UxjDJ2a7%2F46.png?generation=1566513557824702\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwBCx6lJQkgv86X4%2F47.png?generation=1566513554542055\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwBX9G1VfLUKNrvU%2F48.png?generation=1566513557290944\&alt=media)

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

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

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwC3F8saeNGoO2zl%2F49.png?generation=1566513606567286\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwCWnujhjiPIbBrh%2F50.png?generation=1566513615878824\&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://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwCje08fpUa7h3x2%2F51.png?generation=1566513617940919\&alt=media)

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwDEihAEkcsdXxfp%2F52.png?generation=1566513604779116\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwDQsIlX0rsvxO6b%2F53.png?generation=1566513652582478\&alt=media)

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

### NEG

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

Пример:

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwDfnOhSOYggjcbQ%2F54.png?generation=1566513621868354\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwDvbZY9mNEyUCND%2F55.png?generation=1566513587929805\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwE7WxFNKk6qfpZr%2F56.png?generation=1566513638555505\&alt=media)

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwEOjVH9sAJ7hnLu%2F57.png?generation=1566513673801259\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwEapMSp2sxBiWPM%2F58.png?generation=1566513563349459\&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://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwEvHULIk9rD7ipj%2F59.png?generation=1566513594083837\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwFAVvVdNmb2HXNZ%2F60.png?generation=1566513649136566\&alt=media)

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

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

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwFUcy1ZFQhFedKl%2F61.png?generation=1566513601532973\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwFujOLlTICGpvwx%2F62.png?generation=1566513571095942\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwGE67De1CjKem-X%2F63.png?generation=1566513593989125\&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://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwGTB0sjSJeALT69%2F64.png?generation=1566513556228317\&alt=media)

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

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwGwzWAt5Rw4Pw1r%2F65.png?generation=1566513652650615\&alt=media)

Нажимаем F7.

![](https://416819976-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjyqT34OedPJiOdIrDw%2F-LmvTfhKwMHzvDz9duQT%2F-LmvTwHFtfW1clLo6W2W%2F66.png?generation=1566513554619992\&alt=media)

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

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

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

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