OpenWatcom で特に呼び出し規約を指定しない場合のデフォルトの呼び出し規約。
OpenWatcomでは、main()関数は強制的に __watcall 呼び出し規約になる(他の呼び出し規約を指定しても、無視される)。(ただし実験した結果であって、マニュアル・ドキュメント上でこの点について記載されているかは未確認)
※サンプルコードは C言語系/呼び出し規約/x86/fortran の callee.c, caller.c を使用。
※明示的に指定したい場合
int __watcall foobar(); typedef int (__watcall *ptr)();
OpenWatcomのDOS用コンパイラ(wcc.exe)で今回のサンプルコードをコンパイルしたところ、次のような引数の渡し方になっていることが分かった。
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
.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
.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
※サンプルコードは C言語系/呼び出し規約/x86/fortran の callee.c, caller.c を使用。
※明示的に指定したい場合
int __watcall foobar(); typedef int (__watcall *ptr)();
OpenWatcomのDOS用コンパイラ(wcc386.exe)で今回のサンプルコードをコンパイルしたところ、次のような引数の渡し方になっていることが分かった。
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
.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
.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