Light C | ← → 目次 索引 |
Light C で作成した関数をアセンブラなどの他言語のルーチンとリンクする場合は、関数の呼び出し規約を合わせる必要があります。ここでは、Light C で使用される呼び出し規約について説明します。
なお、実際の正確な呼び出し規約を確認するには、-fa で生成されるアセンブラ コードを調べると効果的です。次は、C のソース ファイルと、そこから生成されたアセンブラ コードの例です。
// C のソース int subr( int a, char b, long c ) { a = 1; b = 1; c = 1; return( 4 ); }
; アセンブラ コード | |
public _subr | |
_subr proc near ; line 1 | |
push bp | |
mov bp,sp | |
mov ax,0 | |
call __stack_chk | |
a$ equ [bp+4] ; size=2 | |
b$ equ [bp+6] ; size=1 | |
c$ equ [bp+8] ; size=4 | |
mov word ptr [a$],1h ; line 3 | |
mov byte ptr [b$],1h ; line 4 | |
mov word ptr [c$],1h ; line 5 | |
mov word ptr [c$+2],0h | |
mov ax,4h ; line 6 | |
mov sp,bp | |
pop bp | |
ret | |
_subr endp |
「アセンブラ ルーチンとのリンク」も参照してください。
Light C では、すべての引数がスタック経由で関数に渡されます。
引数は 2 バイト単位でスタックに置かれます。つまり、1 バイトの char 変数は 2 バイト、3 バイトの構造体は 4 バイトのスタック領域を占有します。
関数内では、通常、BP レジスタを使ってスタック上の引数にアクセスします。
戻り値は、サイズに応じてレジスタまたはスタック経由で返されます。次のようになります。
引数
戻り値
型 | サイズ | 返される方法 |
---|---|---|
char | 1 | AL レジスタ経由 |
int | 2 | AX レジスタ経由 |
long | 4 | DX:AX レジスタ経由 |
float | 4 | DX:AX レジスタ経由 |
double | 8 | スタック経由 |
near ポインタ | 2 | AX レジスタ経由 |
far ポインタ | 4 | DX:AX レジスタ経由 |
構造体 | 1 | AL レジスタ経由 |
構造体 | 2 | AX レジスタ経由 |
構造体 | 4 | DX:AX レジスタ経由 |
構造体 | 3, 5〜 | スタック経由 |
関数には、関数名と引数の順序を指定するために、次の修飾子を指定できます。
修飾子 | 「_」の付加 | スタックに引数を積む順序 |
---|---|---|
(なし) | あり | 後から |
syscall | なし | 後から |
stdcall | あり | 前から |
pascal | なし | 前から |
cdecl_r | あり | 後から |
syscall_r | なし | 後から |
stdcall_r | あり | 前から |
pascal_r | なし | 前から |
これらは、API などの特殊な関数を宣言する場合、または特殊なルーチンから呼び出される関数を定義する場合に指定します。
例 | int syscall funcA(int a1, int a2); | // プロトタイプ宣言で |
void pascal funcB(int a1, int a2) { | // 関数定義で | |
... | ||
} |
引数が前からスタックに積まれる stdcall および pascal では、関数の呼び出し側ではなく、関数側がスタックから引数を除去します。
V1.42 以降では、引数を除去する側だけを逆にする cdecl_r、syscall_r、stdcall_r、pascal_r が追加されました。
interrupt 修飾子については、「割り込みハンドラ」を参照してください。
Copyright © Tama Software Ltd, 1999-2012. | ← → 目次 索引 |