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

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

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

C言語系 / 呼び出し規約 / x86 / "WINAPI"他
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, OpenWatcom(32bit), MinGW-gcc 共に、この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

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

プリプロセス結果:

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

.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

プリプロセス結果:

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

.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されている事が分かる。

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

$ gcc -O0 -Wall --save-temps -o winapis winapis.c       
$ winapis.exe 
foo1() = 15
foo2() = 30
foo3() = 150

プリプロセス結果:

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

	.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


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