#navi_header|C言語系| sysycall呼び出し規約は、OS/2 の 32bit API で使われていた。 Linux/BSDでのsyscall(2)とは無関係。 - x86 calling conventions - Wikipedia, the free encyclopedia -- http://en.wikipedia.org/wiki/X86_calling_conventions 2010年の時点のMSDNによると、現在は "__syscall" 呼び出し規約はサポートされていない。(obsoleted) - Obsolete Calling Conventions -- http://msdn.microsoft.com/ja-jp/library/wda6h6df%28VS.80%29.aspx OpenWatcom 1.8 においては、現在もサポートされている。(2010年3月時点) - 関数名の装飾は無し。 - 引数は ''右か左へ'' スタックにPUSHされる。 - ''スタッククリーンアップは関数を呼ぶ側(caller)で実現'' する。 OpenWatcom 1.8 User's manual より: : __syscall (32-bit only) : #block||> 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: + Symbols names are not modified, that is, they are not adorned with leading or trailing underscores. + Arguments are pushed on the stack from right to left. That is, the last argument is pushed first. The calling routine will remove the arguments from the stack. + When a structure is returned, the caller allocates space on the stack. The address of the allocated space will be pushed on the stack immediately before the call instruction. Upon returning from the call, register EAX will contain address of the space allocated for the return value. Floating-point values are returned in 80x87 register ST(0). + Registers EAX, ECX and EDX are not saved and restored when a call is made. ||< #more|| ---- #outline|| ---- * サンプルコード ** callee.c (呼ばれる関数側) #code|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; } 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; } ||< ** caller.c (呼ぶ main() 側) #code|c|> #include 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; } ||< * OpenWatcom Compiler(16bit) : 指定方法 : #block||> int __syscall foobar(); typedef int (__syscall *ptr)(); ||< : コンパイラオプション : "-ecs" : 装飾名 : 装飾無し。 コンパイル&リンク&実行 #pre||> > 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 ||< アセンブラ生成 #pre||> > wdis -a -l=callee.asm callee.obj > wdis -a -l=caller.asm caller.obj ||< ** callee.c のアセンブラ出力(callee.asm) #pre||> .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 ||< ** caller.c のアセンブラ出力(caller.asm) #pre||> .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 ||< * OpenWatcom Compiler(32bit) : 指定方法 : #block||> int __syscall foobar(); typedef int (__syscall *ptr)(); ||< : コンパイラオプション : "-ecs" : 装飾名 : 装飾無し。 コンパイル&リンク&実行 #pre||> > 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 ||< アセンブラ生成 #pre||> > wdis -a -l=callee.asm callee.obj > wdis -a -l=caller.asm caller.obj ||< ** callee.c のアセンブラ出力(callee.asm) #pre||> .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 ||< ** caller.c のアセンブラ出力(caller.asm) #pre||> .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 ||< #navi_footer|C言語系|