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

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

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

ПРОГРАММИРОВАНИЕ НА НЕСКОЛЬКИХ ЯЗЫКАХ

ПОД ПРОГРАММИРОВАНИЕМ НА НЕСКОЛЬКИХ ЯЗЫКАХ МЫ БУДЕМ ПОНИМАТЬ РАЗРАБОТКУ ОДНОЙ ПРОГРАММЫ С ИСПОЛЬЗОВАНИЕМ НЕСКОЛЬКИХ ЯЗЫКОВ И ВЗАИМОДЕЙСТВИЕ ПРОГРАММ, НАПИСАННЫХ НА РАЗНЫХ ЯЗЫКАХ

В программах на Visual C++ и Delphi можно делать ассемблерные вставки. Это называется inline-ассемблером. Обычно inline-ассемблер используется в двух случаях:

1 ЕСЛИ НУЖНО ОПТИМИЗИРОВАТЬ КРИТИЧНЫЕ ПО СКОРОСТИ И НЕБОЛЬШИЕ ПО ОБЪЕМУ УЧАСТКИ ПРОГРАММЫ. ГРАМОТНО НАПИСАННЫЙ АССЕМБЛЕРНЫЙ КОД ВСЕГДА БЫСТРЕЕ КОДА, КОТОРЫЙ ГЕНЕРИРУЕТСЯ КОМПИЛЯТОРОМ C++ ИЛИ DELPHI.

2 НУЖЕН ПРЯМОЙ ДОСТУП К ПАМЯТИ И ПОРТАМ. ЧАЩЕ ВСЕГО ИСПОЛЬЗУЕТСЯ В ДРАЙВЕРАХ, ТАК КАК ИЗ ТРЕТЬЕГО КОЛЬЦА ЗАЩИТЫ С ПОРТАМИ НЕ ОЧЕНЬ-ТО ПОРАБОТАЕШЬ.

Поскольку информации об inline-ассемблерах в интернете довольно мало, мы остановимся на этом подробнее.

[Inline-ассемблер в Visual C++.]

Ассемблерные вставки в исходниках Visual C++ оформляются с помощью блока __asm и выглядят примерно так:

// обычный код на C++

printf("Hello!n");

// а тут ассемблерная вставка

__asm {

mov eax, 2

mov edx, 7

add eax, edx

}

// а потом снова обычный код на C++

printf("Bye!");

Или, что то же самое, так:

// ассемблерная вставка

__asm mov eax, 2

__asm mov edx, 7

__asm add eax, edx

А можно вообще в одну строчку:

// ассемблерная вставка

__asm mov eax, 2 __asm mov edx, 7 __asm add eax, edx

В inline-ассемблере Visual C++ можно использовать все инструкции вплоть до Pentium 4 и AMD Athlon. Поддерживается также MMX. Поддержки Itanium и x64 пока нет :(.

По синтаксису inline-ассемблер Visual C++ частично совпадает с MASM. Например, как и в MASM можно строить выражения с операндами и использовать offset с глобальными переменными (смотри листинг 1). Как и в MASM, можно использовать глобальные метки и принудительно определять короткие переходы (смотри листинг 2). Однако определить локальную метку с помощью @@ в inline-ассемблере Visual C++ не получится – замена lab: на @@lab: в предыдущем примере вызовет ошибку компиляции. Есть и другие отличия от MASM. Например, в inline-ассемблере Visual C++ нет никаких средств для объявления переменных, поэтому про привычные DB, DW, DD, DQ, DT, DF, DUP и THIS можно забыть. Зато можно использовать переменные, объявленные в программе на C++ (смотри листинг 3).

В inline-ассемблере также нельзя объявлять структуры — директивы STRUC, RECORD, WIDTH и MASK недопустимы. Вместо этого можно использовать структуры, объявленные в программе на C++ (смотри листинг 4). Кроме того, в inline-ассемблере можно использовать комментарии и HEX-числа в стиле C++.

В принципе, все отличия подробно описаны в MSDN 2006 (идет в комплекте с Visual Studio 2006).

Обычно в Visual C++ inline-ассемблер используется для написания функций. Как правило, функции, написанные на inline-ассемблере, объявляют с использованием директивы _stdcall. В этом случае параметры передаются в функцию на стеке в обратном порядке, а результат работы возвращается в eax.

Для примера рассмотрим функцию, которая находит длину ASCIIZ-строки:

int _stdcall get_str_length(char *inputstr)

Содержание  Вперед на стр. 071-040-2
ttfb: 2.5098323822021 ms