Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #71, ОКТЯБРЬ 2006 г.

стрельба по-македонски

ДМИТРИЙ КОВАЛЕНКО

Спецвыпуск: Хакер, номер #071, стр. 071-040-2


{

// чаще всего функция целиком состоит из одной

// большой ассемблерной вставки

__asm{

; можно свободно обращаться к переменным,

; переданным в функцию

mov edi, inputstr

mov esi, edi

mov ecx, -1

xor al, al

cld

repne scasb

sub edi, esi

; результат работы функции следует

; возвращать в eax

mov eax, edi

dec eax

}

}

Использовать эту функцию можно так:

int main()

{

char str_1[]="Hello, world!";

int i;

i = get_str_length(str_1);

printf("String: %s\nLength: %d", str_1, i);

}

При написании кода на inline-ассемблере Visual C++ следует помнить некоторые моменты. Во-первых, значения регистров не передаются между ассемблерными вставками. Например, если в ассемблерной вставке ты установил eax в 1, то в следующей ассемблерной вставке eax не обязательно будет равно 1 (смотри листинг 5).

Во-вторых, нужно быть осторожным с регистрами и стеком. В середине ассемблерных вставок нельзя менять регистры ds, ss, sp, bp и флаги. Если эти регистры все-таки меняются, перед выходом из ассемблерной вставки их нужно обязательно восстановить. Что касается стека, то тут нужно соблюдать правило, которое гласит: если в ассемблерной вставке нечто ложится на стек, то в той же ассемблерной вставке это «нечто» должно со стека сниматься.

Рассмотрим, например, такой код:

#include <stdio.h>

// наша функция на ассемблере

void _stdcall Test()

{

__asm{

; кладем на стек eax

push eax

; перед тем как ассемблерная вставка кончится, нужно

; снять eax со стека (например, с помощью pop),

; но мы забыли это сделать ;)

}

}

int main()

{

// вызываем функцию... и любуемся сообщением об ошибке :)

Test();

}

И, наконец, если ты пишешь не драйвер, а обычное Win32-приложение, в ассемблерной вставке не должно быть привилегированных инструкций. Вот, пожалуй, и все про inline-ассемблер Visual C++. Тем, кто хочет узнать больше, советуем почитать MSDN 2006 – там есть вся необходимая информация.

[Inline-ассемблер в Delphi]

во многом похож на inline-ассемблер Visual C++. Поэтому, чтобы не повторяться, мы рассмотрим некоторые моменты вобщем, без подробностей. Ассемблерные вставки в Delphi размещаются между asm и end, например:

{обычный код на Pascal}

Writeln('Hello!');

{вставка на ассемблере}

asm

mov al,1

mov bx,2

end;

{и снова обычный код на Pascal}

Writeln('Bye!');

Inline-ассемблер Delphi поддерживает все инструкции вплоть до Pentium 4 и AMD Athlon. Также можно использовать инструкции AMD 3DNow! для AMD K6 и AMD Enhanced 3DNow! для AMD Athlon. К сожалению, поддержки 64-разрядного кода нет, так что про Itanium и x64 можно забыть.

По синтаксису inline-ассемблер Delphi в основном похож на MASM. Например, поддерживаются выражения MASM и локальные метки. Также разрешено использование offset для глобальных переменных, объявленных в программе (смотри листинг 6). Как и в MASM, можно использовать глобальные метки, но они должны быть объявлены в секции label (смотри листинг 7).

Есть и отличия от MASM. К примеру, комментарии в ассемблерных вставках должны быть обязательно в стиле Delphi, в операторах безусловного перехода нельзя использовать short и т.п. Все эти отличия описаны в документации, которая идет с Borland Developer Studio (файл Reference.pdf).

Назад на стр. 071-040-1  Содержание  Вперед на стр. 071-040-3