На этом шаге мы рассмотрим передачу параметров через регистры.
На этом шаге используется другой тип вызова - быстрый, или регистровый. В соответствии с таблицей 1 шага 85, этот тип вызова предполагает, что три первых параметра будут передаваться в регистрах (ЕАХ, EDX, ECX), а остальные в стеке, как и в случае соглашения stdcall. При этом если стек был задействован, освобождение его возлагается на вызываемую процедуру. Есть еще один нюанс. В случае быстрого вызова транслятор С добавляет к имени символ @ спереди, что мы естественно учитываем в ассемблерном модуле.
#include <windows.h>
#include <stdio.h>
//Объявляется внешняя функция сложения четырех чисел.
extern "C" __fastcall ADDD(DWORD, DWORD, DWORD, DWORD);
void main()
{
DWORD a,b,c,d;
a=1; b=2; c=3; d=4;
printf("%lu\n", (DWORD *)ADDD(a,b,c,d));
ExitProcess(0);
}
Файл add.asm:
.386P .MODEL FLAT, stdcall PUBLIC @ADDD ;Плоская модель памяти. _TEXT SEGMENT DWORD PUBLIC USE32 'CODE' ;Процедура возвращает сумму четырех параметров. ;Передача параметров регистровая. ;Первые три параметра в регистрах EAX, EDX, ECX, ;четвертый параметр в стеке, т.е. [ЕРВ+08Н]. @ADDD PROC PUSH EBP MOV EBP,ESP ADD EAX,ECX ADD EAX,EDX ADD EAX,DWORD PTR [EBP+08H] POP EBP RET 4 @ADDD ENDP _TEXT ENDS END
Трансляция модулей выполняется так:
tasm32 /ml add.asm
А затем включаем add.obj в проект addc (Borland C++ 5.02).
На следующем шаге мы рассмотрим вызовы API.