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

C言語系/呼び出し規約/x86/watcall (v1)

C言語系/呼び出し規約/x86/watcall (v1)

C言語系 / 呼び出し規約 / x86 / watcall (v1)
id: 628 所有者: msakamoto-sf    作成日: 2010-03-19 17:51:00
カテゴリ: Assembler C言語 Windows 

OpenWatcom で特に呼び出し規約を指定しない場合のデフォルトの呼び出し規約。

OpenWatcomでは、main()関数は強制的に __watcall 呼び出し規約になる(他の呼び出し規約を指定しても、無視される)。(ただし実験した結果であって、マニュアル・ドキュメント上でこの点について記載されているかは未確認)



OpenWatcom Compiler(16bit)

※サンプルコードは C言語系/呼び出し規約/x86/fortran の callee.c, caller.c を使用。

指定方法

※明示的に指定したい場合

int __watcall foobar();
typedef int (__watcall *ptr)();
コンパイラオプション
"-ecw",C言語で他の呼び出し規約が指定されていない場合のデフォルト
装飾名
関数名 + "_"

OpenWatcomのDOS用コンパイラ(wcc.exe)で今回のサンプルコードをコンパイルしたところ、次のような引数の渡し方になっていることが分かった。

  • 左から4つまでの引数は、左から順にAX, DX, BX, CXレジスタ経由で渡される。
  • 左から5つ目以降の引数は、右から左へスタックへ積まれる。
  • スタックのクリーンアップは、関数(callee)側で "RET imm16" 命令により実現している。

AX, BXまで使われている点が驚きだが、コード中でEAXやEBXを使うようなより実際のコードの場合、どのように変化するかまでは不明。

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

> wcc -od -d0 -ecw callee.c
> wcc -od -d0 -ecw caller.c
> wcl -fe=watcall16.exe caller.obj callee.obj
> watcall16.exe
foo1() = 20
foo2() = 30
foo3() = 60
foo4() = 100
foo5() = 150
foo6() = 210

アセンブラ生成

> wdis -a -l=callee.asm callee.obj
> wdis -a -l=caller.asm caller.obj

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

.387
		PUBLIC	foo1_
		PUBLIC	foo2_
		PUBLIC	foo3_
		PUBLIC	foo4_
		PUBLIC	foo5_
		PUBLIC	foo6_
		EXTRN	__STK:BYTE
		EXTRN	_small_code_:BYTE
DGROUP		GROUP	CONST,CONST2,_DATA
_TEXT		SEGMENT	BYTE PUBLIC USE16 'CODE'
		ASSUME CS:_TEXT, DS:DGROUP, SS:DGROUP
foo1_:
    push        ax 
    mov         ax,2 
    call        near ptr __STK 
    pop         ax 
    shl         ax,1 
    ret         
foo2_:
    push        ax 
    mov         ax,2 
    call        near ptr __STK 
    pop         ax 
    add         ax,dx 
    ret         
foo3_:
    push        ax 
    mov         ax,2 
    call        near ptr __STK 
    pop         ax 
    add         ax,dx 
    add         ax,bx 
    ret         
foo4_:
    push        ax 
    mov         ax,2 
    call        near ptr __STK 
    pop         ax 
    add         ax,dx 
    add         ax,bx 
    add         ax,cx 
    ret         
foo5_:
    push        ax 
    mov         ax,4 
    call        near ptr __STK 
    pop         ax 
    push        bp 
    mov         bp,sp 
    add         ax,dx 
    add         ax,bx 
    add         ax,cx 
    add         ax,word ptr 4[bp] 
    pop         bp 
    ret         2 
foo6_:
    push        ax 
    mov         ax,4 
    call        near ptr __STK 
    pop         ax 
    push        bp 
    mov         bp,sp 
    add         ax,dx 
    add         ax,bx 
    add         ax,cx 
    add         ax,word ptr 4[bp] 
    add         ax,word ptr 6[bp] 
    pop         bp 
    ret         4 
_TEXT		ENDS
CONST		SEGMENT	WORD PUBLIC USE16 'DATA'
CONST		ENDS
CONST2		SEGMENT	WORD PUBLIC USE16 'DATA'
CONST2		ENDS
_DATA		SEGMENT	WORD PUBLIC USE16 'DATA'
_DATA		ENDS
		END

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

.387
		PUBLIC	main_
		EXTRN	__STK:BYTE
		EXTRN	foo1_:BYTE
		EXTRN	printf_:BYTE
		EXTRN	foo2_:BYTE
		EXTRN	foo3_:BYTE
		EXTRN	foo4_:BYTE
		EXTRN	foo5_:BYTE
		EXTRN	foo6_: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
main_:
    push        ax 
    mov         ax,0aH 
    call        near ptr __STK 
    pop         ax 
    push        bx 
    push        cx 
    mov         ax,0aH 
    call        near ptr foo1_ 
    push        ax 
    mov         ax,offset DGROUP:L$1 
    push        ax 
    call        near ptr printf_ 
    add         sp,4 
    mov         dx,14H 
    mov         ax,0aH 
    call        near ptr foo2_ 
    push        ax 
    mov         ax,offset DGROUP:L$2 
    push        ax 
    call        near ptr printf_ 
    add         sp,4 
    mov         bx,1eH 
    mov         dx,14H 
    mov         ax,0aH 
    call        near ptr foo3_ 
    push        ax 
    mov         ax,offset DGROUP:L$3 
    push        ax 
    call        near ptr printf_ 
    add         sp,4 
    mov         cx,28H 
    mov         bx,1eH 
    mov         dx,14H 
    mov         ax,0aH 
    call        near ptr foo4_ 
    push        ax 
    mov         ax,offset DGROUP:L$4 
    push        ax 
    call        near ptr printf_ 
    add         sp,4 
    mov         ax,32H 
    push        ax 
    mov         cx,28H 
    mov         bx,1eH 
    mov         dx,14H 
    mov         ax,0aH 
    call        near ptr foo5_ 
    push        ax 
    mov         ax,offset DGROUP:L$5 
    push        ax 
    call        near ptr printf_ 
    add         sp,4 
    mov         ax,3cH 
    push        ax 
    mov         ax,32H 
    push        ax 
    mov         cx,28H 
    mov         bx,1eH 
    mov         dx,14H 
    mov         ax,0aH 
    call        near ptr foo6_ 
    push        ax 
    mov         ax,offset DGROUP:L$6 
    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$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
L$4:
    DB	66H, 6fH, 6fH, 34H, 28H, 29H, 20H, 3dH
    DB	20H, 25H, 64H, 0aH, 0
L$5:
    DB	66H, 6fH, 6fH, 35H, 28H, 29H, 20H, 3dH
    DB	20H, 25H, 64H, 0aH, 0
L$6:
    DB	66H, 6fH, 6fH, 36H, 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)

※サンプルコードは C言語系/呼び出し規約/x86/fortran の callee.c, caller.c を使用。

指定方法

※明示的に指定したい場合

int __watcall foobar();
typedef int (__watcall *ptr)();
コンパイラオプション
"-ecw",C言語で他の呼び出し規約が指定されていない場合のデフォルト
装飾名
関数名 + "_"

OpenWatcomのDOS用コンパイラ(wcc386.exe)で今回のサンプルコードをコンパイルしたところ、次のような引数の渡し方になっていることが分かった。

  • 左から4つまでの引数は、左から順にEAX, EDX, EBX, ECXレジスタ経由で渡される。
  • 左から5つ目以降の引数は、右から左へスタックへ積まれる。
  • スタックのクリーンアップは、関数(callee)側で "RET imm16" 命令により実現している。

EAX, EBXまで使われている点が驚きだが、コード中でEAXやEBXを使うようなより実際のコードの場合、どのように変化するかまでは不明。

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

> wcc386 -od -d0 -ecw callee.c
> wcc386 -od -d0 -ecw caller.c
> wcl386 -fe=watcall32.exe caller.obj callee.obj
> watcall32.exe
foo1() = 20
foo2() = 30
foo3() = 60
foo4() = 100
foo5() = 150
foo6() = 210

アセンブラ生成

> wdis -a -l=callee.asm callee.obj
> wdis -a -l=caller.asm caller.obj

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

.387
.386p
.model flat
		PUBLIC	foo1_
		PUBLIC	foo2_
		PUBLIC	foo3_
		PUBLIC	foo4_
		PUBLIC	foo5_
		PUBLIC	foo6_
		EXTRN	__CHK:BYTE
DGROUP		GROUP	CONST,CONST2,_DATA
_TEXT		SEGMENT	BYTE PUBLIC USE32 'CODE'
		ASSUME CS:_TEXT, DS:DGROUP, SS:DGROUP
foo1_:
    push        4 
    call        near ptr FLAT:__CHK 
    add         eax,eax 
    ret         
foo2_:
    push        4 
    call        near ptr FLAT:__CHK 
    add         eax,edx 
    ret         
foo3_:
    push        4 
    call        near ptr FLAT:__CHK 
    add         eax,edx 
    add         eax,ebx 
    ret         
foo4_:
    push        4 
    call        near ptr FLAT:__CHK 
    add         eax,edx 
    add         eax,ebx 
    add         eax,ecx 
    ret         
foo5_:
    push        4 
    call        near ptr FLAT:__CHK 
    add         eax,edx 
    add         ebx,eax 
    lea         eax,[ebx+ecx] 
    add         eax,dword ptr 4[esp] 
    ret         4 
foo6_:
    push        4 
    call        near ptr FLAT:__CHK 
    add         eax,edx 
    add         eax,ebx 
    add         eax,ecx 
    add         eax,dword ptr 4[esp] 
    add         eax,dword ptr 8[esp] 
    ret         8 
_TEXT		ENDS
CONST		SEGMENT	DWORD PUBLIC USE32 'DATA'
CONST		ENDS
CONST2		SEGMENT	DWORD PUBLIC USE32 'DATA'
CONST2		ENDS
_DATA		SEGMENT	DWORD PUBLIC USE32 'DATA'
_DATA		ENDS
		END

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

.387
.386p
.model flat
		PUBLIC	main_
		EXTRN	__CHK:BYTE
		EXTRN	foo1_:BYTE
		EXTRN	printf_:BYTE
		EXTRN	foo2_:BYTE
		EXTRN	foo3_:BYTE
		EXTRN	foo4_:BYTE
		EXTRN	foo5_:BYTE
		EXTRN	foo6_: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
main_:
    push        14H 
    call        near ptr FLAT:__CHK 
    push        ebx 
    push        ecx 
    mov         eax,0aH 
    call        near ptr FLAT:foo1_ 
    push        eax 
    push        offset FLAT:L$1 
    call        near ptr FLAT:printf_ 
    add         esp,8 
    mov         edx,14H 
    mov         eax,0aH 
    call        near ptr FLAT:foo2_ 
    push        eax 
    push        offset FLAT:L$2 
    call        near ptr FLAT:printf_ 
    add         esp,8 
    mov         ebx,1eH 
    mov         edx,14H 
    mov         eax,0aH 
    call        near ptr FLAT:foo3_ 
    push        eax 
    push        offset FLAT:L$3 
    call        near ptr FLAT:printf_ 
    add         esp,8 
    mov         ecx,28H 
    mov         ebx,1eH 
    mov         edx,14H 
    mov         eax,0aH 
    call        near ptr FLAT:foo4_ 
    push        eax 
    push        offset FLAT:L$4 
    call        near ptr FLAT:printf_ 
    add         esp,8 
    push        32H 
    mov         ecx,28H 
    mov         ebx,1eH 
    mov         edx,14H 
    mov         eax,0aH 
    call        near ptr FLAT:foo5_ 
    push        eax 
    push        offset FLAT:L$5 
    call        near ptr FLAT:printf_ 
    add         esp,8 
    push        3cH 
    push        32H 
    mov         ecx,28H 
    mov         ebx,1eH 
    mov         edx,14H 
    mov         eax,0aH 
    call        near ptr FLAT:foo6_ 
    push        eax 
    push        offset FLAT:L$6 
    call        near ptr FLAT:printf_ 
    add         esp,8 
    xor         eax,eax 
    pop         ecx 
    pop         ebx 
    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
L$4:
    DB	66H, 6fH, 6fH, 34H, 28H, 29H, 20H, 3dH
    DB	20H, 25H, 64H, 0aH, 0
L$5:
    DB	66H, 6fH, 6fH, 35H, 28H, 29H, 20H, 3dH
    DB	20H, 25H, 64H, 0aH, 0
L$6:
    DB	66H, 6fH, 6fH, 36H, 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


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2010-03-19 18:06:27
md5:9822a63f4ab0173827cf16ff500085dd
sha1:8233e74b10e61f47f31962f29a8e96903701454d
コメント
コメントを投稿するにはログインして下さい。