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

C言語系/呼び出し規約/x86/"PASCAL" (v2)

C言語系/呼び出し規約/x86/"PASCAL" (v2)

C言語系 / 呼び出し規約 / x86 / "PASCAL" (v2)
id: 626 所有者: msakamoto-sf    作成日: 2010-03-17 17:25:54
カテゴリ: Assembler C言語 Windows 

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

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



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

VC++2008/Borland C++ Compiler/MinGW-gccで "PASCAL" を使うには、Windows用のヘッダーファイルをincludeする必要がある。今回は "windows.h" をincludeした。
windows.hをincludeしない場合、VC++2008/Borland C++ Compilerの両方で関数宣言の構文エラーとなりコンパイルに失敗する。

#include <stdio.h>
#include <windows.h>
 
int PASCAL foo(int a, int b, int c, int d, int e)
{ return a + b + c + d + e; }
 
int main(int argc, char *argv[]) {
    printf("foo() = %d\n", foo(10, 20, 30, 40, 50));
    return 0;
}

VC++2008 Express Edtion (obsoleted)

プリプロセス結果およびアセンブラ出力から、"PASCAL" は "__stdcall" にdefineされている事が分かる。
MSDN上では "obsoleted" となっており、"WINAPI"の方を使うよう推奨されている。

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

> cl /FAs /TC /Od /nologo /c big_pascal.c
> link /SUBSYSTEM:CONSOLE /NOLOGO /OUT:big_pascal.exe big_pascal.obj
> big_pascal.exe
foo() = 150

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

> cl /P /TC /Od /nologo /c big_pascal.c

プリプロセス結果:

#line 3 "big_pascal.c"
 
int __stdcall foo(int a, int b, int c, int d, int e)
{ return a + b + c + d + e; }
 
int main(int argc, char *argv[]) {
    printf("foo() = %d\n", foo(10, 20, 30, 40, 50));
    return 0;
}

アセンブラ出力(big_pascal.asm)

; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.30729.01 

	TITLE	C:\in_vitro\c\cc_vc\big_pascal.c
	.686P
	.XMM
	include listing.inc
	.model	flat

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

_DATA	SEGMENT
$SG78588 DB	'foo() = %d', 0aH, 00H
_DATA	ENDS
PUBLIC	_foo@20
; Function compile flags: /Odtp
; File c:\in_vitro\c\cc_vc\big_pascal.c
_TEXT	SEGMENT
_a$ = 8							; size = 4
_b$ = 12						; size = 4
_c$ = 16						; size = 4
_d$ = 20						; size = 4
_e$ = 24						; size = 4
_foo@20	PROC

; 5    : { 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
_foo@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

; 7    : int main(int argc, char *argv[]) {

	push	ebp
	mov	ebp, esp

; 8    : 	printf("foo() = %d\n", foo(10, 20, 30, 40, 50));

	push	50					; 00000032H
	push	40					; 00000028H
	push	30					; 0000001eH
	push	20					; 00000014H
	push	10					; 0000000aH
	call	_foo@20
	push	eax
	push	OFFSET $SG78588
	call	_printf
	add	esp, 8

; 9    : 	return 0;

	xor	eax, eax

; 10   : }

	pop	ebp
	ret	0
_main	ENDP
_TEXT	ENDS
END

Borland C++ Compiler

プリプロセス結果およびアセンブラ出力から、"PASCAL" は "__stdcall" にdefineされている事が分かる。

アセンブラコードを生成

> bcc32 -S big_pascal.c

コンパイル&実行

> bcc32 big_pascal.c
> big_pascal.exe
foo() = 150

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

> cpp32 big_pascal.c

プリプロセス結果:

/* big_pascal.c 3: */
/* big_pascal.c 4: */int __stdcall foo(int a, int b, int c, int d, int e)
/* big_pascal.c 5: */{ return a + b + c + d + e; }
/* big_pascal.c 6: */
/* big_pascal.c 7: */int main(int argc, char *argv[]) {
/* big_pascal.c 8: */printf("foo() = %d\n", foo(10, 20, 30, 40, 50));
/* big_pascal.c 9: */return 0;
/* big_pascal.c 10: */}

アセンブラ出力(big_pascal.asm)

	.386p
	ifdef ??version
	if    ??version GT 500H
	.mmx
	endif
	endif
	model flat
	ifndef	??version
	?debug	macro
	endm
	endif
	?debug	S "big_pascal.c"
	?debug	T "big_pascal.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'
foo	proc	near
?live1@0:
   ;	
   ;	int PASCAL foo(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
foo	endp
_main	proc	near
?live1@48:
   ;	
   ;	int main(int argc, char *argv[]) {
   ;	
	push      ebp
	mov       ebp,esp
   ;	
   ;		printf("foo() = %d\n", foo(10, 20, 30, 40, 50));
   ;	
@4:
	push      50
	push      40
	push      30
	push      20
	push      10
	call      foo
	push      eax
	push      offset s@
	call      _printf
	add       esp,8
   ;	
   ;		return 0;
   ;	
	xor       eax,eax
   ;	
   ;	}
   ;	
@6:
@5:
	pop       ebp
	ret 
_main	endp
_TEXT	ends
_DATA	segment dword public use32 'DATA'
s@	label	byte
	;	s@+0:
	db	"foo() = %d",10,0
	align	4
_DATA	ends
_TEXT	segment dword public use32 'CODE'
_TEXT	ends
	public	foo
	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 "big_pascal.c" 15473 34993
	end

OpenWatcom Compiler(16bit)

OpenWatcom Compiler(32bit)

GCC-3.4.5, MinGW-5.1.6, MSYS 1.0

プリプロセス結果およびアセンブラ出力から、"PASCAL" は "__attribute__()"版stdcall にdefineされている事が分かる。

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

$ gcc -O0 -Wall --save-temps -o big_pascal big_pascal.c 
$ big_pascal.exe 
foo() = 150

プリプロセス結果:

# 3 "big_pascal.c" 2
 
int __attribute__((__stdcall__)) foo(int a, int b, int c, int d, int e)
{ return a + b + c + d + e; }
 
int main(int argc, char *argv[]) {
 printf("foo() = %d\n", foo(10, 20, 30, 40, 50));
 return 0;
}

アセンブラ出力(big_pascal.asm)

	.file	"big_pascal.c"
	.text
.globl _foo@20
	.def	_foo@20;	.scl	2;	.type	32;	.endef
_foo@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 "foo() = %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	$50, 16(%esp)
	movl	$40, 12(%esp)
	movl	$30, 8(%esp)
	movl	$20, 4(%esp)
	movl	$10, (%esp)
	call	_foo@20
	subl	$20, %esp
	movl	%eax, 4(%esp)
	movl	$LC0, (%esp)
	call	_printf
	movl	$0, %eax
	leave
	ret
	.def	_printf;	.scl	2;	.type	32;	.endef


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