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

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

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

C言語系 / 呼び出し規約 / x86 / pascal (v4)
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



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