
Использование __fastcall
Последний тип вызова __fastcall. Аргументы передаются в ECX и EDX. Остальные заталкиваются в стек справа налево. За счет использования регистров передача параметров ускоряется. Стек очищает функция. (По-прежнему включена оптимизация).
функция main
00401030 push 1042h
00401035 mov edx,15h
0040103A mov cl,61h
0040103C call 00401000
подпрограмма
00401000 mov eax,dword ptr [esp+4]
00401004 inc eax
00401005 inc edx
00401006 inc cl
00401008 push eax
00401009 movsx edx,dx
0040100C movsx eax,cl
0040100F push edx
00401010 push eax
00401011 push 406030h
00401016 call 00401050
0040101B add esp,10h
0040101E ret 4
Мы видим, что через регистры передаются первые два параметра. Остальные параметры (в нашем случае всего один) передаются через стек.
Объединение программы на Си и подпрограммы на языке Ассемблера в среде VC++
Недостаток включения ассемблерного кода в текст программы на Си с помощью директивы __asm: отключается оптимизация, нет переносимости программы на другие платформы. Поэтому представляет интерес следующий подход: помещать подпрограмму на языке Ассемблера в отдельный файл и отдельно ее ассемблировать. Далее с помощью компоновщика объединять файлы.
Рассмотрим пример
Из программе на Си мы будем вызывать подпрограмму, которая умножает целое число на заданную степень двойки.
m.c
include <stdio.h>
int power2( int num, int power );
void main()
{
printf( "3 times 2 to the power of 5 is %d\n", \
power2( 3, 5) );
}
Подпрограмма осуществляет умножение числа num на 2^power с помощью нескольких сдвигов влево.
f.asm
.386
.MODEL flat,C
PUBLIC power2
.CODE
power2 PROC
ARG num:dword, power:dword
mov eax, num
mov ecx, power
shl eax, cl
ret
power2 ENDP
END
Нам нужно получить объектный файл в 32-разрядном формате, поэтому нужно воспользоваться не tasm.exe, а tasm32.exe. Заодно посмотрим листинг этой программы.
c:\tasm\bin\tasm32/l/mx f.asm
f.lst
1 .386
2 00000000 .MODEL flat,C
3 PUBLIC power2
4 00000000 .CODE
5 00000000 power2 PROC
6 ARG num:dword, power:dword
1 7 00000000 C8 0000 00 ENTERD 00000h,0
1 8 00000004 8B 45 08 mov eax, num
9 00000007 8B 4D 0C mov ecx, power
10 0000000A D3 E0 shl eax, cl
1 11 0000000C C9 LEAVED
1 12 0000000D C3 RET 00000h
13 0000000E power2 ENDP
-
END
…
num Number [FLAT:EBP+0008]
power Number [FLAT:EBP+000C]
power2 (_power2) Near32 FLAT:0000
Groups & Segments Bit Size Align Combine Class
DGROUP Group
_DATA 32 0000 Dword Public DATA
FLAT Group
_TEXT 32 000E Dword Public CODE
При построении проекта мы воспользуемся командой Project/ Add to Project/ Files и добавим файл f.obj. При компоновке мы получим предупреждение:
f.OBJ : warning LNK4033: converting object format from OMF to COFF
The format of the object file is OMF. This tool requires COFF input. To permanently convert the file, run EDITBIN on the file with no options.
Это означает следующее: tasm32 генерирует объектный файл в формате OMF — Object Module Format. Фирма Microsoft разработала собственный формат обьектных файлов COFF — Common Object File Format. Компоновщик предварительно преобразует один формат в другой.
При запуске программа выдает 96 (= 3 * 32)
Вот что мы увидим в окне Disassembly
00401000 push 5
00401002 push 3
00401004 call 00401020
00401009 push eax
0040100A push 406030h
0040100F call 0040102E
00401014 add esp,10h
00401017 ret
00401018 nop
…
0040101F nop
00401020 enter 0,0
00401024 mov eax,dword ptr [ebp+8]
00401027 mov ecx,dword ptr [ebp+0Ch]
0040102A shl eax,cl
0040102C leave
0040102D ret
К сожалению, если мы используем tasm для создания объектного файла, мы не можем использовать отладочную информацию. Среда VC++ "не понимает" отладочную информацию, включаемую tasm в объектный файл. Поэтому лучше использовать MASM фирмы Microsoft.
ml /Cx /coff /Zi /c /Fl f.asm
Получим файлы f.obj и f.lst. Расшифруем используемые ключи:
/Cx Preserve case in publics, externs (Сохранить регистр букв во внешних именах)
/coff Generate COFF format object file (Генерировать объектный файл в COFF-формате)
/Zi Add symbolic debug info (Добавить отладочную информацию)
/c Assemble without linking (Только ассемблировать, не компоновать)
/Fl Generate listing (Генерировать файл листинга)