sysycall呼び出し規約は、OS/2 の 32bit API で使われていた。
Linux/BSDでのsyscall(2)とは無関係。
2010年の時点のMSDNによると、現在は "__syscall" 呼び出し規約はサポートされていない。(obsoleted)
OpenWatcom 1.8 においては、現在もサポートされている。(2010年3月時点)
OpenWatcom 1.8 User's manual より:
The __syscall keyword may be used with function definitions, and indicates that the calling convention used is compatible with functions provided by 32-bit OS/2.
Notes:
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; } int foo5(int a, int b, int c, int d, int e) { return a + b + c + d + e; } int foo6(int a, int b, int c, int d, int e, int f) { return a + b + c + d + e + f; }
#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); extern int foo5(int a, int b, int c, int d, int e); extern int foo6(int a, int b, int c, int d, int e, int f); 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)); printf("foo5() = %d\n", foo5(10, 20, 30, 40, 50)); printf("foo6() = %d\n", foo6(10, 20, 30, 40, 50, 60)); return 0; }
int __syscall foobar(); typedef int (__syscall *ptr)();
コンパイル&リンク&実行
> wcc -od -d0 -ecs callee.c > wcc -od -d0 -ecs caller.c > wcl -fe=syscall16.exe caller.obj callee.obj > syscall16.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:
mov ax,4
call near ptr __STK
push bp
mov bp,sp
mov ax,word ptr 4[bp]
shl ax,1
pop bp
ret
foo2:
mov ax,4
call near ptr __STK
push bp
mov bp,sp
mov ax,word ptr 4[bp]
add ax,word ptr 6[bp]
pop bp
ret
foo3:
mov ax,4
call near ptr __STK
push bp
mov bp,sp
mov ax,word ptr 4[bp]
add ax,word ptr 6[bp]
add ax,word ptr 8[bp]
pop bp
ret
foo4:
mov ax,4
call near ptr __STK
push bp
mov bp,sp
mov ax,word ptr 4[bp]
add ax,word ptr 6[bp]
add ax,word ptr 8[bp]
add ax,word ptr 0aH[bp]
pop bp
ret
foo5:
mov ax,4
call near ptr __STK
push bp
mov bp,sp
mov ax,word ptr 4[bp]
add ax,word ptr 6[bp]
add ax,word ptr 8[bp]
add ax,word ptr 0aH[bp]
add ax,word ptr 0cH[bp]
pop bp
ret
foo6:
mov ax,4
call near ptr __STK
push bp
mov bp,sp
mov ax,word ptr 4[bp]
add ax,word ptr 6[bp]
add ax,word ptr 8[bp]
add ax,word ptr 0aH[bp]
add ax,word ptr 0cH[bp]
add ax,word ptr 0eH[bp]
pop bp
ret
_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,12H
call near ptr __STK
pop ax
push bx
push cx
mov ax,0aH
push ax
call near ptr foo1
add sp,2
push ax
mov ax,offset DGROUP:L$1
push ax
call near ptr printf_
add sp,4
mov ax,14H
push ax
mov ax,0aH
push ax
call near ptr foo2
add sp,4
push ax
mov ax,offset DGROUP:L$2
push ax
call near ptr printf_
add sp,4
mov ax,1eH
push ax
mov ax,14H
push ax
mov ax,0aH
push ax
call near ptr foo3
add sp,6
push ax
mov ax,offset DGROUP:L$3
push ax
call near ptr printf_
add sp,4
mov ax,28H
push ax
mov ax,1eH
push ax
mov ax,14H
push ax
mov ax,0aH
push ax
call near ptr foo4
add sp,8
push ax
mov ax,offset DGROUP:L$4
push ax
call near ptr printf_
add sp,4
mov ax,32H
push ax
mov ax,28H
push ax
mov ax,1eH
push ax
mov ax,14H
push ax
mov ax,0aH
push ax
call near ptr foo5
add sp,0aH
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 ax,28H
push ax
mov ax,1eH
push ax
mov ax,14H
push ax
mov ax,0aH
push ax
call near ptr foo6
add sp,0cH
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
int __syscall foobar(); typedef int (__syscall *ptr)();
コンパイル&リンク&実行
> wcc386 -od -d0 -ecs callee.c > wcc386 -od -d0 -ecs caller.c > wcl386 -fe=syscall32.exe caller.obj callee.obj > syscall32.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
mov eax,dword ptr 4[esp]
add eax,eax
ret
foo2:
push 4
call near ptr FLAT:__CHK
mov eax,dword ptr 4[esp]
add eax,dword ptr 8[esp]
ret
foo3:
push 4
call near ptr FLAT:__CHK
mov eax,dword ptr 4[esp]
add eax,dword ptr 8[esp]
add eax,dword ptr 0cH[esp]
ret
foo4:
push 4
call near ptr FLAT:__CHK
mov eax,dword ptr 4[esp]
add eax,dword ptr 8[esp]
add eax,dword ptr 0cH[esp]
add eax,dword ptr 10H[esp]
ret
foo5:
push 4
call near ptr FLAT:__CHK
mov eax,dword ptr 4[esp]
add eax,dword ptr 8[esp]
add eax,dword ptr 0cH[esp]
add eax,dword ptr 10H[esp]
add eax,dword ptr 14H[esp]
ret
foo6:
push 4
call near ptr FLAT:__CHK
mov eax,dword ptr 4[esp]
add eax,dword ptr 8[esp]
add eax,dword ptr 0cH[esp]
add eax,dword ptr 10H[esp]
add eax,dword ptr 14H[esp]
add eax,dword ptr 18H[esp]
ret
_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 20H
call near ptr FLAT:__CHK
push ecx
push 0aH
call near ptr FLAT:foo1
add esp,4
push eax
push offset FLAT:L$1
call near ptr FLAT:printf_
add esp,8
push 14H
push 0aH
call near ptr FLAT:foo2
add esp,8
push eax
push offset FLAT:L$2
call near ptr FLAT:printf_
add esp,8
push 1eH
push 14H
push 0aH
call near ptr FLAT:foo3
add esp,0cH
push eax
push offset FLAT:L$3
call near ptr FLAT:printf_
add esp,8
push 28H
push 1eH
push 14H
push 0aH
call near ptr FLAT:foo4
add esp,10H
push eax
push offset FLAT:L$4
call near ptr FLAT:printf_
add esp,8
push 32H
push 28H
push 1eH
push 14H
push 0aH
call near ptr FLAT:foo5
add esp,14H
push eax
push offset FLAT:L$5
call near ptr FLAT:printf_
add esp,8
push 3cH
push 32H
push 28H
push 1eH
push 14H
push 0aH
call near ptr FLAT:foo6
add esp,18H
push eax
push offset FLAT:L$6
call near ptr FLAT:printf_
add esp,8
xor eax,eax
pop ecx
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