#navi_header|C言語系| "PASCAL"はヘッダーファイルで定義された呼び出し規約で、"__pascal"呼び出し規約のこと ''ではない。'' 実際にどの呼び出し規約("__stdcall", "__cdecl", "__pascal", ...)になるかは、OS/コンパイラによって異なってくるので、使用する場合は注意が必要。 ''ただし、2010年現在の Win32 APIプラットフォームにおいては基本的に PASCAL == "__stdcall" と考えて良い。'' VC++2008, Borland C++ Compiler, MinGW-gcc 共に、PASCALは"__stdcall"にdefineされている。 #more|| ---- #outline|| ---- * サンプルコード(big_pascal.c) VC++2008/Borland C++ Compiler/MinGW-gccで "PASCAL" を使うには、Windows用のヘッダーファイルをincludeする必要がある。今回は "windows.h" をincludeした。 windows.hをincludeしない場合、VC++2008/Borland C++ Compilerの両方で関数宣言の構文エラーとなりコンパイルに失敗する。 #code|c|> #include #include 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"の方を使うよう推奨されている。 - Obsolete Calling Conventions (C++) -- http://msdn.microsoft.com/ja-jp/library/wda6h6df%28VS.80%29.aspx コンパイル&リンク&実行 #pre||> > 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 プリプロセス結果: #code|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) #pre||> ; 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 コンパイル&実行 #pre||> > bcc32 big_pascal.c > big_pascal.exe foo() = 150 ||< プリプロセス結果を生成: > cpp32 big_pascal.c プリプロセス結果: #code|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) #pre||> .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されている事が分かる。 コンパイル&リンク&実行 #pre||> $ gcc -O0 -Wall --save-temps -o big_pascal big_pascal.c $ big_pascal.exe foo() = 150 ||< プリプロセス結果: #code|c|> # 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) #pre||> .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 ||< #navi_footer|C言語系|