- •Системное программное обеспечение
- •Использование ассемблера с языками высокого уровня
- •Использование ассемблера с языками высокого уровня
- •Использование ассемблера с языками высокого уровня
- •Использование ассемблера с языками высокого уровня
- •Использование ассемблера с языками высокого уровня
- •Использование ассемблера с языками высокого уровня
- •Использование ассемблера с языками высокого уровня
- •Использование ассемблера с языками высокого уровня
- •Использование ассемблера с языками высокого уровня
- •Использование ассемблера с языками высокого уровня
- •Использование ассемблера с языками высокого уровня
- •Использование ассемблера с языками высокого уровня
- •Использование ассемблера с языками высокого уровня
- •Использование ассемблера с языками высокого уровня
- •Использование ассемблера с языками высокого уровня
- •Использование ассемблера с языками высокого уровня
Использование ассемблера с языками высокого уровня
эквивалентно
proc1(param1,param2);
proc2(param1,param2);
и это — одна из причин, почему компиляторы с языка С создают более компактный и быстрый код по сравнению с другими языками.
В таблице ниже представлены основные соглашения по передаче параметров в процедуру.
Соглашение |
Параметры |
Очистка стека |
Регистры |
|
register (fastcall) |
|
|
EAX, EDX, ECX (Delphi) |
|
(быстрый |
Слева направо |
Процедура |
||
ECX, EDX (Visual C++ .NET) |
||||
или регистровый вызов) |
|
|
||
|
|
|
||
pascal |
Слева направо |
Процедура |
Нет |
|
(конвенция языка Паскаль) |
||||
cdecl |
Справа налево |
Вызывающая |
Нет |
|
(конвенция С) |
|
программа |
|
|
stdcall |
Справа налево |
Процедура |
Нет |
|
(стандартный вызов) |
||||
|
|
|
||
Safecall |
Справа налево |
Процедура |
Нет |
Использование ассемблера с языками высокого уровня
Таблица объясняет соглашения о передаче параметров. Например, передача параметров stdcall отличается и от С, и от PASCAL-конвенций. Она применяется для всех системных функций Win32 API. Здесь параметры помещаются в стек в обратном порядке, как в С, но процедуры должны очищать стек сами, как в PASCAL.
Еще одно интересное отклонение от С-конвенции можно наблюдать в Watcom С. Этот компилятор использует регистры для ускорения работы, и параметры в функции передаются по возможности через регистры. Например, при вызове функции
some_proc(a,b,с,d,e,f);
первые четыре параметра передаются соответственно в (Е)АХ, (E)DX, (Е)ВХ, (Е)СХ, а только начиная с пятого, параметры помещают в стек в обычном обратном порядке:
Использование ассемблера с языками высокого уровня
e |
equ |
[bp+4] |
f |
equ |
[bp+6] |
Еще один важный момент - тип возвращаемых функцией данных. С точки зрения ассемблера здесь все просто: в регистре EAX возвращается значение, которое может быть либо числом, либо указателем на переменную или структуру. Если возвращаемое число типа WORD, то оно содержится в младшем слове регистра EAX.
Cогласование имен идентификаторов. Компиляторы Microsoft С (а также многие компиляторы в UNIX) изменяют названия процедур, чтобы отразить способ передачи параметров. Так, к названиям всех процедур, использующих С-конвенцию, приписывается символ подчеркивания. То есть, если в С-программе записано
some_proc();
Использование ассемблера с языками высокого уровня
то реально компилятор пишет call _some_proc
и это означает, что, если эта процедура написана на ассемблере, она должна называться именно _some_proc (или использовать сложную форму записи директивы proc).
Названия процедур, использующих stdcall, например, при создании DLL, искажаются еще более сложным образом: спереди к называнию процедуры добавляется символ подчеркивания, а сзади — символ @ и размер занимаемой параметрами области стека в байтах, (то есть в точности число, стоящее после команды ret в конце процедуры).
some_proc(a:word);
превращается в
Использование ассемблера с языками высокого уровня
push a
call _some_proc@4
Если требуется выполнить совсем небольшую операцию на ассемблере, например вызвать какое-то прерывание или преобразовать сложную битовую структуру, часто нерационально создавать отдельный файл ради нескольких строк на ассемблере. Чтобы этого избежать, многие языки высокого уровня поддерживают возможность вставки ассемблерного кода непосредственно в программу.
Например, нужно написать процедуру, возвращающую слово, находящееся по адресу 0040h:006Ch, в BIOS — счетчик сигналов системного таймера, который удобно использовать для инициализации генераторов случайных чисел.
Использование ассемблера с языками высокого уровня
Пример. Pascal
function get_seed:longint var
seed:longint begin
asm
push |
es |
mov |
ax,0040h |
mov |
es,ax |
mov |
ax,es:[006Ch] |
mov |
seed,ax |
pop |
es |
end; get_seed:=seed;
end;
Использование ассемблера с языками высокого уровня
Пример. C
int get_seed() |
|
int seed; |
|
{ |
|
_asm { |
|
push |
es |
mov |
ax,0040h |
mov |
es,ax |
mov |
ax,es:[006Ch] |
mov |
seed,ax |
pop |
es |
};
return(seed);
};
В этих ситуациях ассемблерная программа может свободно пользоваться переменными из языка высокого уровня, так как они автоматически преобразуются в соответствующие выражения типа word ptr [bp+4].
