Ассемблер — это просто хадкорный ассемблер


Объяснение ассемблера на сишных примерах


Основной ассемблерной командой является команда пересылки данных MOV, которую можно уподобить оператору присвоения. c = 0x333 на языке ассемблера записывается так: MOV EAX, 333h (обратите внимание на разницу записи шестнадцатеричных чисел!). Можно так же записать MOV EAX, EBX

(записать в регистр EAX значение регистра EBX).

Указатели заключаются в квадратные скобки. Сишное a = *b

на ассемблере записывается так: MOV EAX, [EBX]. При желании, к указателю можно добавить смещение: a = b[0x66]

эквивалентно: MOV EAX, [EBX + 0x66].

Переменные объявляются директивами DB (переменная в один байт), DW (переменная в одно слово), DD (переменная в двойное слово) и т.д. Знаковость переменных при их объявлении не указывается. Одна и та же переменная в различных участках программы может интерпретироваться и как число со знаком и как число без знака. Для загрузки переменной в указатель применяется либо команда LEA, либо MOV с директивой offset. Покажем это на следующем примере:

LEA EDX,b     ;// регистр EDX содержит указатель на переменную b

MOV EBX,a     ;// регистр EBX содержит значение переменной a

MOV ECX, offset a // регистр ECX

содержит указатель на переменную a

MOV

[EDX],EBX ;// скопировать переменную a b

MOV b, EBX    ;// скопировать переменную a b



MOV b, a      ;// !!!ошибка!!! так делать нельзя!!!

              ;// оба аргумента команды MOV не могут быть в памяти!

a

DD 66h;// объявляем переменную a типа двойного слова и инициализируем ее числом 66h

b

DD ? ;// объявляем неинициализированную переменную b

типа двойного слова

Листинг 1 основные типа пересылок данных

Теперь перейдем к условным переходам. Никакого "if" на ассемблере нет и эту операцию приходится осуществлять в два этапа. Команда CMP позволяет сравнить два числа, сохраняя результат своей работы во флагах. Флаги — это биты специального регистра, описание которого заняло бы слишком много места и поэтому здесь не рассматривается. Достаточно запомнить три основных состояния: меньше (bellow или less), больше (above или great) и равно (equal). Семейство команд условного перехода Jxx проверяют условие xx и, если оно истинно, совершают прыжок по указанному адресу. Например, JE прыгает, если числа равны (Jump if Equal), а JNE если неравны (Jump if Not Equal). JB/JA работают с беззнаковыми числами, а с JL/JG — со знаковыми. Любы два не противоречащих друг другу условия могут быть скомбинированы друг с другом, например: JBE — переход если одно беззнаковое число меньше другого или равно ему. Безусловный переход осуществляется командой JMP.


Конструкция CMP/ Jxx больше всего похожа на Бейсковское IF xxx GOTO, чем на Си. Вот несколько примеров ее использования:

CMP EAX, EBX         ;// сравнить EAX

и EBX

JZ xxx               ;// если они равны переход на xxx

CMP

[ECX], EDX       ;// сравнить *ECX

и EDX

JAE yyy                    ;// если беззнаковый *ECX

>= EDX

перейти на yyy

Листинг 2 основные типы условных переходов

Вызов функций на ассемблере реализуется намного сложнее, чем на Си. Во-первых, существует по меньшей мере два типа соглашений — Си и Паскаль. В Си-соглашении параметры в функцию передаются справа налево, а из стека их вычищает вызывающий функцию код. В Паскаль соглашении все происходит наоборот! Аргументы передаются слева направо, а из стека из вычищает сама функция. Большинство API-функций операционный системы Windows придерживаются комбинированного соглашения stdcall, при котором аргументы заносятся в соответствии с Си-соглашением, а из стека вычищаются по соглашению Паскаль. Возвращаемое функцией значение помещается в регистр EAX или (для передачи 64-разрядных значений используется регистровая пара EDX:EAX). Разумеется, этих соглашением необходимо придерживаться только при вызове внешних функций (API, библиотек и т. д.)."Внутренние" функции им следовать не обязаны и могут передавать аргументы любым мыслимым способом, например, через регистры.

Вот простейший пример вызовафункции:

PUSH offset LibName        ;// засылаем в стек смещение строки

CALL LoadLibrary           ;// вызов функции

MOV h, EAX                  ;// EAX содержит возращенное значение

Листинг 3 вызов API-функции операционной системы


Содержание раздела