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

C言語系/呼び出し規約/x86/pascal (v5)

C言語系/呼び出し規約/x86/pascal (v5)

C言語系 / 呼び出し規約 / x86 / pascal (v5)
id: 619 所有者: msakamoto-sf    作成日: 2010-03-17 10:32:44
カテゴリ: Assembler C言語 UNIX Windows 

__pascal呼び出し規約:

  • 引数はスタック上にPUSHする。(主に左から右へPUSH)
  • 関数(callee)側でスタックをクリーンアップする。
    • アセンブラレベルではRET imm16命令を使って、戻る時にスタックポインタを"imm16"バイト分だけ戻す。つまり、"imm16"バイト分だけSPが増える(x86ではスタックはアドレスの小さい方へ進んでいくので、「戻る」=SPのアドレス値は大きくなる)。


サンプルコード

callee.c (呼ばれる関数側)

int foo1(int a) { return a * 2; }
int foo2(int a, int b) { return a + b; }
int foo3(int a, int b, int c) { return a + b + c; }
int foo4(int a, int b, int c, int d) { return a + b + c + d; }

caller.c (呼ぶ main() 側)

#include <stdio.h>
 
extern int foo1(int a);
extern int foo2(int a, int b);
extern int foo3(int a, int b, int c);
extern int foo4(int a, int b, int c, int d);
 
int __cdecl main(int argc, char *argv[])
{
    printf("foo1() = %d\n", foo1(10));
    printf("foo2() = %d\n", foo2(10, 20));
    printf("foo3() = %d\n", foo3(10, 20, 30));
    printf("foo4() = %d\n", foo4(10, 20, 30, 40));
    return 0;
}

VC++2008 Express Edtion (obsoleted)

2010年現在、VC++2008では "__pascal" 呼び出し規約はサポートされていない。(obsoleted)

実際に次のようなコード(pascal.c)をコンパイルしようとすると、関数宣言のところでエラーになり、コンパイルに失敗する。

#include <stdio.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;
}

コンパイル→エラー、失敗:

> cl /TC /Od /nologo /c pascal.c
pascal.c
pascal.c(3) : error C2061: 構文エラー : 識別子 'foo'
pascal.c(3) : error C2059: 構文エラー : ';'
pascal.c(3) : error C2059: 構文エラー : '型'

Borland C++ Compiler

指定方法
int __pascal foobar();
typedef int (__pascal *ptr)();
コンパイラオプション
"-p"
装飾名
関数名の英字が全て大文字に変換される。

アセンブラコードを生成

> bcc32 -Od -p -S callee.c
> bcc32 -Od -p -S caller.c

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

> bcc32 -Od -p -c -ocallee_pascal.obj callee.c
> bcc32 -Od -p -c -ocaller_pascal.obj caller.c
> ilink32 /c /ap /Tpe c0x32 caller_pascal callee_pascal, pascal, , cw32 import32
> pascal.exe
foo1() = 20
foo2() = 30
foo3() = 60
foo4() = 100

callee.c のアセンブラ出力(callee.asm)

	.386p
	ifdef ??version
	if    ??version GT 500H
	.mmx
	endif
	endif
	model flat
	ifndef	??version
	?debug	macro
	endm
	endif
	?debug	S "callee.c"
	?debug	T "callee.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:
   ;	
   ;	int foo1(int a) { return a * 2; }
   ;	
	push      ebp
	mov       ebp,esp
@1:
	mov       eax,dword ptr [ebp+8]
	add       eax,eax
@3:
@2:
	pop       ebp
	ret       4
FOO1	endp
FOO2	proc	near
?live1@32:
   ;	
   ;	int foo2(int a, int b) { return a + b; }
   ;	
	push      ebp
	mov       ebp,esp
@4:
	mov       eax,dword ptr [ebp+12]
	add       eax,dword ptr [ebp+8]
@6:
@5:
	pop       ebp
	ret       8
FOO2	endp
FOO3	proc	near
?live1@64:
   ;	
   ;	int foo3(int a, int b, int c) { return a + b + c; }
   ;	
	push      ebp
	mov       ebp,esp
@7:
	mov       eax,dword ptr [ebp+16]
	add       eax,dword ptr [ebp+12]
	add       eax,dword ptr [ebp+8]
@9:
@8:
	pop       ebp
	ret       12
FOO3	endp
FOO4	proc	near
?live1@96:
   ;	
   ;	int foo4(int a, int b, int c, int d) { return a + b + c + d; }
   ;	
	push      ebp
	mov       ebp,esp
@10:
	mov       eax,dword ptr [ebp+20]
	add       eax,dword ptr [ebp+16]
	add       eax,dword ptr [ebp+12]
	add       eax,dword ptr [ebp+8]
@12:
@11:
	pop       ebp
	ret       16
FOO4	endp
_TEXT	ends
	public	FOO1
	public	FOO2
	public	FOO3
	public	FOO4
	?debug	D "callee.c" 15473 24064
	end

caller.cのアセンブラ出力(caller.asm)

	.386p
	ifdef ??version
	if    ??version GT 500H
	.mmx
	endif
	endif
	model flat
	ifndef	??version
	?debug	macro
	endm
	endif
	?debug	S "caller.c"
	?debug	T "caller.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'
_main	proc	near
?live1@0:
   ;	
   ;	int __cdecl main(int argc, char *argv[])
   ;	
	push      ebp
	mov       ebp,esp
   ;	
   ;	{
   ;		printf("foo1() = %d\n", foo1(10));
   ;	
@1:
	push      10
	call      FOO1
	push      eax
	push      offset s@
	call      _printf
	add       esp,8
   ;	
   ;		printf("foo2() = %d\n", foo2(10, 20));
   ;	
	push      10
	push      20
	call      FOO2
	push      eax
	push      offset s@+13
	call      _printf
	add       esp,8
   ;	
   ;		printf("foo3() = %d\n", foo3(10, 20, 30));
   ;	
	push      10
	push      20
	push      30
	call      FOO3
	push      eax
	push      offset s@+26
	call      _printf
	add       esp,8
   ;	
   ;		printf("foo4() = %d\n", foo4(10, 20, 30, 40));
   ;	
	push      10
	push      20
	push      30
	push      40
	call      FOO4
	push      eax
	push      offset s@+39
	call      _printf
	add       esp,8
   ;	
   ;		return 0;
   ;	
	xor       eax,eax
   ;	
   ;	}
   ;	
@3:
@2:
	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
	;	s@+39:
	db	"foo4() = %d",10,0
	align	4
_DATA	ends
_TEXT	segment dword public use32 'CODE'
_TEXT	ends
	public	_main
 extrn   __setargv__:near
 extrn   _printf:near
 extrn   FOO1:near
 extrn   FOO2:near
 extrn   FOO3:near
 extrn   FOO4:near
	?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 "caller.c" 15473 24232
	end

OpenWatcom Compiler(16bit)

OpenWatcom Compiler(32bit)

Turbo C++ 4.0J(TC4J)

TC4Jで、コマンドラインからの呼び出し規約指定オプションが不明だった為、gcc系列と同様、CALLINGCONVを"-D"でdefineすることにより切り替える方式を採った。
なお、TC4Jについてはリンク&実行までは行っていない。

指定方法
int __pascal foobar();
typedef int (__pascal *ptr)();
装飾名
関数名の英字が全て大文字に変換される。

アセンブラコードを生成

> tcc -DCALLINGCONV=__pascal -S callee.c
> tcc -DCALLINGCONV=__pascal -S caller.c

callee.c のアセンブラ出力(callee.asm)

	.286p
	ifndef	??version
?debug	macro
	endm
publicdll macro	name
	public	name
	endm
$comm	macro	name,dist,size,count
	comm	dist name:BYTE:count*size
	endm
	else
$comm	macro	name,dist,size,count
	comm	dist name[size]:BYTE:count
	endm
	endif
	?debug	V 301h
	?debug	S "callee.c"
	?debug	C E91593723C0863616C6C65652E63
_TEXT	segment byte public 'CODE'
_TEXT	ends
DGROUP	group	_DATA,_BSS
	assume	cs:_TEXT,ds:DGROUP
_DATA	segment word public 'DATA'
d@	label	byte
d@w	label	word
_DATA	ends
_BSS	segment word public 'BSS'
b@	label	byte
b@w	label	word
_BSS	ends
_TEXT	segment byte public 'CODE'
   ;	
   ;	int CALLINGCONV foo1(int a) { return a * 2; }
   ;	
	assume	cs:_TEXT,ds:DGROUP
FOO1	proc	near
	push	bp
	mov	bp,sp
	mov	ax,word ptr [bp+4]
	add	ax,ax
	pop	bp
	ret	2
	pop	bp
	ret	2
FOO1	endp
   ;	
   ;	int CALLINGCONV foo2(int a, int b) { return a + b; }
   ;	
	assume	cs:_TEXT,ds:DGROUP
FOO2	proc	near
	push	bp
	mov	bp,sp
	mov	ax,word ptr [bp+6]
	add	ax,word ptr [bp+4]
	pop	bp
	ret	4
	pop	bp
	ret	4
FOO2	endp
   ;	
   ;	int CALLINGCONV foo3(int a, int b, int c) { return a + b + c; }
   ;	
	assume	cs:_TEXT,ds:DGROUP
FOO3	proc	near
	push	bp
	mov	bp,sp
	mov	ax,word ptr [bp+8]
	add	ax,word ptr [bp+6]
	add	ax,word ptr [bp+4]
	pop	bp
	ret	6
	pop	bp
	ret	6
FOO3	endp
   ;	
   ;	int CALLINGCONV foo4(int a, int b, int c, int d) { return a + b + c + d; }
   ;	
	assume	cs:_TEXT,ds:DGROUP
FOO4	proc	near
	push	bp
	mov	bp,sp
	mov	ax,word ptr [bp+10]
	add	ax,word ptr [bp+8]
	add	ax,word ptr [bp+6]
	add	ax,word ptr [bp+4]
	pop	bp
	ret	8
	pop	bp
	ret	8
FOO4	endp
	?debug	C E9
	?debug	C FA00000000
_TEXT	ends
_DATA	segment word public 'DATA'
s@	label	byte
_DATA	ends
_TEXT	segment byte public 'CODE'
_TEXT	ends
_s@	equ	s@
	public	FOO1
	public	FOO2
	public	FOO3
	public	FOO4
	end

caller.c のアセンブラ出力(caller.asm)

	.286p
	ifndef	??version
?debug	macro
	endm
publicdll macro	name
	public	name
	endm
$comm	macro	name,dist,size,count
	comm	dist name:BYTE:count*size
	endm
	else
$comm	macro	name,dist,size,count
	comm	dist name[size]:BYTE:count
	endm
	endif
	?debug	V 301h
	?debug	S "caller.c"
	?debug	C E9D2A0723C0863616C6C65722E63
	?debug	C E900207F1E16433A5C5443345C494E434C5544455C737464696F2E+
	?debug	C 68
	?debug	C E900207F1E16433A5C5443345C494E434C5544455C5F646566732E+
	?debug	C 68
	?debug	C E900207F1E17433A5C5443345C494E434C5544455C5F6E66696C65+
	?debug	C 2E68
	?debug	C E900207F1E16433A5C5443345C494E434C5544455C5F6E756C6C2E+
	?debug	C 68
_TEXT	segment byte public 'CODE'
_TEXT	ends
DGROUP	group	_DATA,_BSS
	assume	cs:_TEXT,ds:DGROUP
_DATA	segment word public 'DATA'
d@	label	byte
d@w	label	word
_DATA	ends
_BSS	segment word public 'BSS'
b@	label	byte
b@w	label	word
_BSS	ends
_TEXT	segment byte public 'CODE'
   ;	
   ;	int __cdecl main(int argc, char *argv[])
   ;	
	assume	cs:_TEXT,ds:DGROUP
_main	proc	near
	push	bp
	mov	bp,sp
   ;	
   ;	{
   ;	    printf("foo1() = %d\n", foo1(10));
   ;	
	push	10
	call	near ptr FOO1
	push	ax
	push	offset DGROUP:s@
	call	near ptr _printf
	add	sp,4
   ;	
   ;	    printf("foo2() = %d\n", foo2(10, 20));
   ;	
	push	10
	push	20
	call	near ptr FOO2
	push	ax
	push	offset DGROUP:s@+13
	call	near ptr _printf
	add	sp,4
   ;	
   ;	    printf("foo3() = %d\n", foo3(10, 20, 30));
   ;	
	push	10
	push	20
	push	30
	call	near ptr FOO3
	push	ax
	push	offset DGROUP:s@+26
	call	near ptr _printf
	add	sp,4
   ;	
   ;	    printf("foo4() = %d\n", foo4(10, 20, 30, 40));
   ;	
	push	10
	push	20
	push	30
	push	40
	call	near ptr FOO4
	push	ax
	push	offset DGROUP:s@+39
	call	near ptr _printf
	add	sp,4
   ;	
   ;	    return 0;
   ;	
	xor	ax,ax
	pop	bp
	ret	
   ;	
   ;	}
   ;	
	pop	bp
	ret	
_main	endp
	?debug	C E9
	?debug	C FA00000000
_TEXT	ends
_DATA	segment word public 'DATA'
s@	label	byte
	db	'foo1() = %d'
	db	10
	db	0
	db	'foo2() = %d'
	db	10
	db	0
	db	'foo3() = %d'
	db	10
	db	0
	db	'foo4() = %d'
	db	10
	db	0
_DATA	ends
_TEXT	segment byte public 'CODE'
_TEXT	ends
_s@	equ	s@
	extrn	_printf:near
	extrn	FOO1:near
	extrn	FOO2:near
	extrn	FOO3:near
	extrn	FOO4:near
	public	_main
	extrn	__setargv__:far
	end


プレーンテキスト形式でダウンロード
表示中のバージョン : 5
現在のバージョン : 6
更新者: msakamoto-sf
更新日: 2010-03-19 17:17:18
md5:9940698c420c090d8bc938fbda5b7722
sha1:4e7d0030fcc25ba17e7c6143d1aed17c39aa7b7b
コメント
コメントを投稿するにはログインして下さい。