#navi_header|C言語系| ''"WINAPI", "CALLBACK", "APIENTRY"'' はヘッダーファイルで定義された呼び出し規約で、実際にどの呼び出し規約("__stdcall", "__cdecl", "__pascal", ...)になるかは OS/コンパイラによって異なってくるので、使用する場合は注意が必要。 ''ただし、2010年現在の Win32 APIプラットフォームにおいては基本的にどれも "__stdcall" と考えて良い。'' VC++2008, Borland C++ Compiler, OpenWatcom(32bit), MinGW-gcc 共に、この3つは"__stdcall"にdefineされている。 #more|| ---- #outline|| ---- * サンプルコード(winapis.c) WINAPI, CALLBACK, APIENTRY はWin32API用なので、使うにはWindows用のヘッダーファイルをincludeする必要がある。今回は "windows.h" をincludeした。 #code|c|> #include #include int WINAPI foo1(int a, int b, int c, int d, int e) { return a + b + c + d + e; } int CALLBACK foo2(int a, int b, int c, int d, int e) { return a + b + c + d + e; } int APIENTRY foo3(int a, int b, int c, int d, int e) { return a + b + c + d + e; } int main(int argc, char *argv[]) { printf("foo1() = %d\n", foo1(1, 2, 3, 4, 5)); printf("foo2() = %d\n", foo2(6, 7, 8, 9, 0)); printf("foo3() = %d\n", foo3(10, 20, 30, 40, 50)); return 0; } ||< * VC++2008 Express Edtion プリプロセス結果およびアセンブラ出力から、"__stdcall" にdefineされている事が分かる。 コンパイル&リンク&実行 #pre||> > cl /FAs /TC /Od /nologo /c winapis.c > link /SUBSYSTEM:CONSOLE /NOLOGO /OUT:winapis.exe winapis.obj > winapis.exe foo1() = 15 foo2() = 30 foo3() = 150 ||< プリプロセス結果を生成: > cl /P /TC /Od /nologo /c winapis.c プリプロセス結果: #code|c|> #line 3 "winapis.c" int __stdcall foo1(int a, int b, int c, int d, int e) { return a + b + c + d + e; } int __stdcall foo2(int a, int b, int c, int d, int e) { return a + b + c + d + e; } int __stdcall foo3(int a, int b, int c, int d, int e) { return a + b + c + d + e; } int main(int argc, char *argv[]) { printf("foo1() = %d\n", foo1(1, 2, 3, 4, 5)); printf("foo2() = %d\n", foo2(6, 7, 8, 9, 0)); printf("foo3() = %d\n", foo3(10, 20, 30, 40, 50)); return 0; } ||< ** アセンブラ出力(winapis.asm) #pre||> ; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.30729.01 TITLE C:\in_vitro\c\cc_vc\winapis.c .686P .XMM include listing.inc .model flat INCLUDELIB LIBCMT INCLUDELIB OLDNAMES _DATA SEGMENT $SG78612 DB 'foo1() = %d', 0aH, 00H ORG $+3 $SG78613 DB 'foo2() = %d', 0aH, 00H ORG $+3 $SG78614 DB 'foo3() = %d', 0aH, 00H _DATA ENDS PUBLIC _foo1@20 ; Function compile flags: /Odtp ; File c:\in_vitro\c\cc_vc\winapis.c _TEXT SEGMENT _a$ = 8 ; size = 4 _b$ = 12 ; size = 4 _c$ = 16 ; size = 4 _d$ = 20 ; size = 4 _e$ = 24 ; size = 4 _foo1@20 PROC ; 6 : { return a + b + c + d + e; } push ebp mov ebp, esp mov eax, DWORD PTR _a$[ebp] add eax, DWORD PTR _b$[ebp] add eax, DWORD PTR _c$[ebp] add eax, DWORD PTR _d$[ebp] add eax, DWORD PTR _e$[ebp] pop ebp ret 20 ; 00000014H _foo1@20 ENDP _TEXT ENDS PUBLIC _foo2@20 ; Function compile flags: /Odtp _TEXT SEGMENT _a$ = 8 ; size = 4 _b$ = 12 ; size = 4 _c$ = 16 ; size = 4 _d$ = 20 ; size = 4 _e$ = 24 ; size = 4 _foo2@20 PROC ; 10 : { return a + b + c + d + e; } push ebp mov ebp, esp mov eax, DWORD PTR _a$[ebp] add eax, DWORD PTR _b$[ebp] add eax, DWORD PTR _c$[ebp] add eax, DWORD PTR _d$[ebp] add eax, DWORD PTR _e$[ebp] pop ebp ret 20 ; 00000014H _foo2@20 ENDP _TEXT ENDS PUBLIC _foo3@20 ; Function compile flags: /Odtp _TEXT SEGMENT _a$ = 8 ; size = 4 _b$ = 12 ; size = 4 _c$ = 16 ; size = 4 _d$ = 20 ; size = 4 _e$ = 24 ; size = 4 _foo3@20 PROC ; 14 : { return a + b + c + d + e; } push ebp mov ebp, esp mov eax, DWORD PTR _a$[ebp] add eax, DWORD PTR _b$[ebp] add eax, DWORD PTR _c$[ebp] add eax, DWORD PTR _d$[ebp] add eax, DWORD PTR _e$[ebp] pop ebp ret 20 ; 00000014H _foo3@20 ENDP _TEXT ENDS PUBLIC _main EXTRN _printf:PROC ; Function compile flags: /Odtp _TEXT SEGMENT _argc$ = 8 ; size = 4 _argv$ = 12 ; size = 4 _main PROC ; 16 : int main(int argc, char *argv[]) { push ebp mov ebp, esp ; 17 : printf("foo1() = %d\n", foo1(1, 2, 3, 4, 5)); push 5 push 4 push 3 push 2 push 1 call _foo1@20 push eax push OFFSET $SG78612 call _printf add esp, 8 ; 18 : printf("foo2() = %d\n", foo2(6, 7, 8, 9, 0)); push 0 push 9 push 8 push 7 push 6 call _foo2@20 push eax push OFFSET $SG78613 call _printf add esp, 8 ; 19 : printf("foo3() = %d\n", foo3(10, 20, 30, 40, 50)); push 50 ; 00000032H push 40 ; 00000028H push 30 ; 0000001eH push 20 ; 00000014H push 10 ; 0000000aH call _foo3@20 push eax push OFFSET $SG78614 call _printf add esp, 8 ; 20 : return 0; xor eax, eax ; 21 : } pop ebp ret 0 _main ENDP _TEXT ENDS END ||< * Borland C++ Compiler プリプロセス結果およびアセンブラ出力から、"__stdcall" にdefineされている事が分かる。 アセンブラコードを生成 > bcc32 -S winapis.c コンパイル&実行 #pre||> > bcc32 winapis.c > winapis.exe foo1() = 15 foo2() = 30 foo3() = 150 ||< プリプロセス結果を生成: > cpp32 winapis.c プリプロセス結果: #code|c|> /* winapis.c 3: */ /* winapis.c 4: */int __stdcall /* winapis.c 5: */foo1(int a, int b, int c, int d, int e) /* winapis.c 6: */{ return a + b + c + d + e; } /* winapis.c 7: */ /* winapis.c 8: */int __stdcall /* winapis.c 9: */foo2(int a, int b, int c, int d, int e) /* winapis.c 10: */{ return a + b + c + d + e; } /* winapis.c 11: */ /* winapis.c 12: */int __stdcall /* winapis.c 13: */foo3(int a, int b, int c, int d, int e) /* winapis.c 14: */{ return a + b + c + d + e; } /* winapis.c 15: */ /* winapis.c 16: */int main(int argc, char *argv[]) { /* winapis.c 17: */printf("foo1() = %d\n", foo1(1, 2, 3, 4, 5)); /* winapis.c 18: */printf("foo2() = %d\n", foo2(6, 7, 8, 9, 0)); /* winapis.c 19: */printf("foo3() = %d\n", foo3(10, 20, 30, 40, 50)); /* winapis.c 20: */return 0; /* winapis.c 21: */} ||< ** アセンブラ出力(winapis.asm) #pre||> .386p ifdef ??version if ??version GT 500H .mmx endif endif model flat ifndef ??version ?debug macro endm endif ?debug S "winapis.c" ?debug T "winapis.c" _TEXT segment dword public use32 'CODE' _TEXT ends _DATA segment dword public use32 'DATA' _DATA ends _BSS segment dword public use32 'BSS' _BSS ends DGROUP group _BSS,_DATA _TEXT segment dword public use32 'CODE' foo1 proc near ?live1@0: ; ; foo1(int a, int b, int c, int d, int e) ; push ebp mov ebp,esp ; ; { return a + b + c + d + e; } ; @1: mov eax,dword ptr [ebp+8] add eax,dword ptr [ebp+12] add eax,dword ptr [ebp+16] add eax,dword ptr [ebp+20] add eax,dword ptr [ebp+24] @3: @2: pop ebp ret 20 foo1 endp foo2 proc near ?live1@48: ; ; foo2(int a, int b, int c, int d, int e) ; push ebp mov ebp,esp ; ; { return a + b + c + d + e; } ; @4: mov eax,dword ptr [ebp+8] add eax,dword ptr [ebp+12] add eax,dword ptr [ebp+16] add eax,dword ptr [ebp+20] add eax,dword ptr [ebp+24] @6: @5: pop ebp ret 20 foo2 endp foo3 proc near ?live1@96: ; ; foo3(int a, int b, int c, int d, int e) ; push ebp mov ebp,esp ; ; { return a + b + c + d + e; } ; @7: mov eax,dword ptr [ebp+8] add eax,dword ptr [ebp+12] add eax,dword ptr [ebp+16] add eax,dword ptr [ebp+20] add eax,dword ptr [ebp+24] @9: @8: pop ebp ret 20 foo3 endp _main proc near ?live1@144: ; ; int main(int argc, char *argv[]) { ; push ebp mov ebp,esp ; ; printf("foo1() = %d\n", foo1(1, 2, 3, 4, 5)); ; @10: push 5 push 4 push 3 push 2 push 1 call foo1 push eax push offset s@ call _printf add esp,8 ; ; printf("foo2() = %d\n", foo2(6, 7, 8, 9, 0)); ; push 0 push 9 push 8 push 7 push 6 call foo2 push eax push offset s@+13 call _printf add esp,8 ; ; printf("foo3() = %d\n", foo3(10, 20, 30, 40, 50)); ; push 50 push 40 push 30 push 20 push 10 call foo3 push eax push offset s@+26 call _printf add esp,8 ; ; return 0; ; xor eax,eax ; ; } ; @12: @11: pop ebp ret _main endp _TEXT ends _DATA segment dword public use32 'DATA' s@ label byte ; s@+0: db "foo1() = %d",10,0 ; s@+13: db "foo2() = %d",10,0 ; s@+26: db "foo3() = %d",10,0 align 4 _DATA ends _TEXT segment dword public use32 'CODE' _TEXT ends public foo1 public foo2 public foo3 public _main extrn __setargv__:near extrn _printf:near ?debug C 9F757569642E6C6962 ?debug C 9F757569642E6C6962 ?debug D "C:\in_vitro\apps\borland\bcc55\include\imm.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\mcx.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\winsvc.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\commdlg.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\oleauto.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\propidl.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\oaidl.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\msxml.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\servprov.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\oleidl.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\urlmon.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\cguid.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\objidl.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\unknwn.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\search.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\stdlib.h" 10521 10272 ?debug D "C:\in_vitro\apps\borland\bcc55\include\objbase.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\ole2.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\prsht.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\winspool.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\winsmcrd.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\winioctl.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\rpcnsip.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\rpcndr.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\wtypes.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\winscard.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\winefs.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\wincrypt.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\qos.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\winsock2.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\winperf.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\shellapi.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\rpcasync.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\rpcnterr.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\rpcnsi.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\rpcdcep.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\rpcdce.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\rpc.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\nb30.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\mmsystem.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\lzexpand.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\dlgs.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\ddeml.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\dde.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\cderr.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\winnetwk.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\winreg.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\winver.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\wincon.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\winnls.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\tvout.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\winuser.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\pshpack1.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\wingdi.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\winerror.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\winbase.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\pshpack8.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\pshpack2.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\poppack.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\pshpack4.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\mem.h" 10521 10272 ?debug D "C:\in_vitro\apps\borland\bcc55\include\_loc.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\locale.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\_str.h" 10521 10272 ?debug D "C:\in_vitro\apps\borland\bcc55\include\string.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\guiddef.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\basetsd.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\mbctype.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\ctype.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\winnt.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\windef.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\stdarg.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\excpt.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\windows.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\_nfile.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\_null.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\_defs.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\_stddef.h" 10339 10240 ?debug D "C:\in_vitro\apps\borland\bcc55\include\stdio.h" 10339 10240 ?debug D "winapis.c" 15473 36482 end ||< * OpenWatcom Compiler(16bit) プリプロセス結果およびアセンブラ出力から、"WINAPI"と"CALLBACK" は "__far __pascal" にdefineされている事が分かる。 ''※16bit用のヘッダーファイルではAPIENTRYが未定義の為、コメントアウトして確認している。'' コンパイル&リンク&実行 > set INCLUDE=%WATCOM%\h;%WATCOM%\h\win > wcl winapis.c アセンブラ生成: > wdis -a -l=winapis.asm winapis.obj プリプロセス結果を生成: > wcl -pcl -fo winapis.i winapis.c プリプロセス結果: #code|c|> #line 2 "winapis.c" int __far __pascal foo1(int a, int b, int c, int d, int e) { return a + b + c + d + e; } int __far __pascal foo2(int a, int b, int c, int d, int e) { return a + b + c + d + e; } /* int APIENTRY foo3(int a, int b, int c, int d, int e) { return a + b + c + d + e; } */ int main(int argc, char *argv[]) { printf("foo1() = %d\n", foo1(1, 2, 3, 4, 5)); printf("foo2() = %d\n", foo2(6, 7, 8, 9, 0)); /*printf("foo3() = %d\n", foo3(10, 20, 30, 40, 50));*/ return 0; } ||< ** アセンブラ出力(winapis.asm) #pre||> .387 PUBLIC FOO1 PUBLIC FOO2 PUBLIC main_ EXTRN __STK:BYTE EXTRN printf_:BYTE EXTRN __argc:BYTE EXTRN _small_code_:BYTE EXTRN _cstart_:BYTE DGROUP GROUP CONST,CONST2,_DATA _TEXT SEGMENT BYTE PUBLIC USE16 'CODE' ASSUME CS:_TEXT, DS:DGROUP, SS:DGROUP FOO1: mov ax,6 L$1: call near ptr __STK push bp mov bp,sp mov ax,word ptr 0eH[bp] add ax,word ptr 0cH[bp] add ax,word ptr 0aH[bp] add ax,word ptr 8[bp] add ax,word ptr 6[bp] pop bp retf 0aH FOO2: mov ax,6 jmp L$1 main_: push ax mov ax,10H call near ptr __STK pop ax push bx push cx mov ax,1 push ax mov ax,2 push ax mov ax,3 push ax mov ax,4 push ax mov ax,5 push ax push cs call near ptr FOO1 push ax mov ax,offset DGROUP:L$2 push ax call near ptr printf_ add sp,4 mov ax,6 push ax mov ax,7 push ax mov ax,8 push ax mov ax,9 push ax xor ax,ax push ax push cs call near ptr FOO2 push ax mov ax,offset DGROUP:L$3 push ax call near ptr printf_ add sp,4 xor ax,ax pop cx pop bx ret _TEXT ENDS CONST SEGMENT WORD PUBLIC USE16 'DATA' L$2: DB 66H, 6fH, 6fH, 31H, 28H, 29H, 20H, 3dH DB 20H, 25H, 64H, 0aH, 0 L$3: DB 66H, 6fH, 6fH, 32H, 28H, 29H, 20H, 3dH DB 20H, 25H, 64H, 0aH, 0 CONST ENDS CONST2 SEGMENT WORD PUBLIC USE16 'DATA' CONST2 ENDS _DATA SEGMENT WORD PUBLIC USE16 'DATA' _DATA ENDS END ||< * OpenWatcom Compiler(32bit) プリプロセス結果およびアセンブラ出力から、"__stdcall" にdefineされている事が分かる。 コンパイル&リンク&実行 > set INCLUDE=%WATCOM%\h;%WATCOM%\h\nt > wcl386 winapis.c アセンブラ生成: > wdis -a -l=winapis.asm winapis.obj プリプロセス結果を生成: > wcl386 -pcl -fo winapis.i winapis.c プリプロセス結果: #code|c|> #line 2 "winapis.c" int __stdcall foo1(int a, int b, int c, int d, int e) { return a + b + c + d + e; } int __stdcall foo2(int a, int b, int c, int d, int e) { return a + b + c + d + e; } int __stdcall foo3(int a, int b, int c, int d, int e) { return a + b + c + d + e; } int main(int argc, char *argv[]) { printf("foo1() = %d\n", foo1(1, 2, 3, 4, 5)); printf("foo2() = %d\n", foo2(6, 7, 8, 9, 0)); printf("foo3() = %d\n", foo3(10, 20, 30, 40, 50)); return 0; } ||< ** アセンブラ出力(winapis.asm) #pre||> .387 .386p .model flat PUBLIC `_foo1@20` PUBLIC `_foo2@20` PUBLIC `_foo3@20` PUBLIC main_ EXTRN __CHK:BYTE EXTRN printf_:BYTE EXTRN __argc:BYTE EXTRN _cstart_:BYTE DGROUP GROUP CONST,CONST2,_DATA _TEXT SEGMENT BYTE PUBLIC USE32 'CODE' ASSUME CS:_TEXT, DS:DGROUP, SS:DGROUP `_foo1@20`: push 4 call near ptr FLAT:__CHK mov eax,dword ptr 4[esp] add eax,dword ptr 8[esp] add eax,dword ptr 0cH[esp] add eax,dword ptr 10H[esp] add eax,dword ptr 14H[esp] ret 14H `_foo2@20`: push 4 call near ptr FLAT:__CHK mov eax,dword ptr 4[esp] add eax,dword ptr 8[esp] add eax,dword ptr 0cH[esp] add eax,dword ptr 10H[esp] add eax,dword ptr 14H[esp] ret 14H `_foo3@20`: push 4 call near ptr FLAT:__CHK mov eax,dword ptr 4[esp] add eax,dword ptr 8[esp] add eax,dword ptr 0cH[esp] add eax,dword ptr 10H[esp] add eax,dword ptr 14H[esp] ret 14H main_: push 1cH call near ptr FLAT:__CHK push ecx push 5 push 4 push 3 push 2 push 1 call near ptr FLAT:`_foo1@20` push eax push offset FLAT:L$1 call near ptr FLAT:printf_ add esp,8 push 0 push 9 push 8 push 7 push 6 call near ptr FLAT:`_foo2@20` push eax push offset FLAT:L$2 call near ptr FLAT:printf_ add esp,8 push 32H push 28H push 1eH push 14H push 0aH call near ptr FLAT:`_foo3@20` push eax push offset FLAT:L$3 call near ptr FLAT:printf_ add esp,8 xor eax,eax pop ecx ret _TEXT ENDS CONST SEGMENT DWORD PUBLIC USE32 'DATA' L$1: DB 66H, 6fH, 6fH, 31H, 28H, 29H, 20H, 3dH DB 20H, 25H, 64H, 0aH, 0 L$2: DB 66H, 6fH, 6fH, 32H, 28H, 29H, 20H, 3dH DB 20H, 25H, 64H, 0aH, 0 L$3: DB 66H, 6fH, 6fH, 33H, 28H, 29H, 20H, 3dH DB 20H, 25H, 64H, 0aH, 0 CONST ENDS CONST2 SEGMENT DWORD PUBLIC USE32 'DATA' CONST2 ENDS _DATA SEGMENT DWORD PUBLIC USE32 'DATA' _DATA ENDS END ||< * GCC-3.4.5, MinGW-5.1.6, MSYS 1.0 プリプロセス結果およびアセンブラ出力から、"__attribute__()"版stdcall にdefineされている事が分かる。 コンパイル&リンク&実行 #pre||> $ gcc -O0 -Wall --save-temps -o winapis winapis.c $ winapis.exe foo1() = 15 foo2() = 30 foo3() = 150 ||< プリプロセス結果: #code|c|> # 3 "winapis.c" 2 int __attribute__((__stdcall__)) foo1(int a, int b, int c, int d, int e) { return a + b + c + d + e; } int __attribute__((__stdcall__)) foo2(int a, int b, int c, int d, int e) { return a + b + c + d + e; } int __attribute__((__stdcall__)) foo3(int a, int b, int c, int d, int e) { return a + b + c + d + e; } int main(int argc, char *argv[]) { printf("foo1() = %d\n", foo1(1, 2, 3, 4, 5)); printf("foo2() = %d\n", foo2(6, 7, 8, 9, 0)); printf("foo3() = %d\n", foo3(10, 20, 30, 40, 50)); return 0; } ||< ** アセンブラ出力(winapis.asm) #pre||> .file "winapis.c" .text .globl _foo1@20 .def _foo1@20; .scl 2; .type 32; .endef _foo1@20: pushl %ebp movl %esp, %ebp movl 12(%ebp), %eax addl 8(%ebp), %eax addl 16(%ebp), %eax addl 20(%ebp), %eax addl 24(%ebp), %eax popl %ebp ret $20 .globl _foo2@20 .def _foo2@20; .scl 2; .type 32; .endef _foo2@20: pushl %ebp movl %esp, %ebp movl 12(%ebp), %eax addl 8(%ebp), %eax addl 16(%ebp), %eax addl 20(%ebp), %eax addl 24(%ebp), %eax popl %ebp ret $20 .globl _foo3@20 .def _foo3@20; .scl 2; .type 32; .endef _foo3@20: pushl %ebp movl %esp, %ebp movl 12(%ebp), %eax addl 8(%ebp), %eax addl 16(%ebp), %eax addl 20(%ebp), %eax addl 24(%ebp), %eax popl %ebp ret $20 .def ___main; .scl 2; .type 32; .endef .section .rdata,"dr" LC0: .ascii "foo1() = %d\12\0" LC1: .ascii "foo2() = %d\12\0" LC2: .ascii "foo3() = %d\12\0" .text .globl _main .def _main; .scl 2; .type 32; .endef _main: pushl %ebp movl %esp, %ebp subl $24, %esp andl $-16, %esp movl $0, %eax addl $15, %eax addl $15, %eax shrl $4, %eax sall $4, %eax movl %eax, -4(%ebp) movl -4(%ebp), %eax call __alloca call ___main movl $5, 16(%esp) movl $4, 12(%esp) movl $3, 8(%esp) movl $2, 4(%esp) movl $1, (%esp) call _foo1@20 subl $20, %esp movl %eax, 4(%esp) movl $LC0, (%esp) call _printf movl $0, 16(%esp) movl $9, 12(%esp) movl $8, 8(%esp) movl $7, 4(%esp) movl $6, (%esp) call _foo2@20 subl $20, %esp movl %eax, 4(%esp) movl $LC1, (%esp) call _printf movl $50, 16(%esp) movl $40, 12(%esp) movl $30, 8(%esp) movl $20, 4(%esp) movl $10, (%esp) call _foo3@20 subl $20, %esp movl %eax, 4(%esp) movl $LC2, (%esp) call _printf movl $0, %eax leave ret .def _printf; .scl 2; .type 32; .endef ||< #navi_footer|C言語系|