home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

C言語系/呼び出し規約/x86/"WINAPI"他 (v1)

C言語系/呼び出し規約/x86/"WINAPI"他 (v1)

C言語系 / 呼び出し規約 / x86 / "WINAPI"他 (v1)
id: 627 所有者: msakamoto-sf    作成日: 2010-03-17 17:52:51
カテゴリ: Assembler C言語 Windows 

"WINAPI", "CALLBACK", "APIENTRY"はヘッダーファイルで定義された呼び出し規約で、実際にどの呼び出し規約("__stdcall", "__cdecl", "__pascal", ...)になるかは OS/コンパイラによって異なってくるので、使用する場合は注意が必要。

ただし、2010年現在の Win32 APIプラットフォームにおいては基本的にどれも "__stdcall" と考えて良い。
VC++2008, Borland C++ Compiler共に、この3つは"__stdcall"にdefineされている。



サンプルコード(winapis.c)

WINAPI, CALLBACK, APIENTRY はWin32API用なので、使うにはWindows用のヘッダーファイルをincludeする必要がある。今回は "windows.h" をincludeした。

#include <stdio.h>
#include <windows.h>
 
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されている事が分かる。

コンパイル&リンク&実行

> 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

プリプロセス結果:

#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)

; 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

コンパイル&実行

> bcc32 winapis.c
> winapis.exe
foo1() = 15
foo2() = 30
foo3() = 150

プリプロセス結果を生成:

> cpp32 winapis.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)

	.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

MinGW/MSYS

OpenWatcom Compiler(16bit)

OpenWatcom Compiler(32bit)



プレーンテキスト形式でダウンロード
表示中のバージョン : 1
現在のバージョン : 3
更新者: msakamoto-sf
更新日: 2010-03-19 20:32:19
md5:a639fbdc235b7f64ba769b2ac563810e
sha1:2d0b62d932ed85397c756359c1e166ca32271583
コメント
コメントを投稿するにはログインして下さい。