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