home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

C言語系/呼び出し規約/x86/stdcall (v2)

C言語系/呼び出し規約/x86/stdcall (v2)

C言語系 / 呼び出し規約 / x86 / stdcall (v2)
id: 616 所有者: msakamoto-sf    作成日: 2010-03-17 10:28:45
カテゴリ: Assembler C言語 UNIX Windows 

__stdcall呼び出し規約:

  • 引数はスタック上にPUSHする。(主に右から左へPUSH)
  • 関数(callee)側でスタックをクリーンアップする。
    • アセンブラレベルではRET imm16命令を使って、戻る時にスタックポインタを"imm16"バイト分だけ戻す。つまり、"imm16"バイト分だけSPが増える(x86ではスタックはアドレスの小さい方へ進んでいくので、「戻る」=SPのアドレス値は大きくなる)。


サンプルコード

callee.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; }

caller.c (呼ぶ main() 側)

#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);
 
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));
    return 0;
}

VC++2008 Express Edtion

指定方法
int __stdcall foobar();
typedef int (__stdcall *ptr)();
コンパイラオプション
"/Gz"
装飾名
"_" + 関数名 + "@" + スタックのバイト数

コンパイル&リンク&実行

> cl /FAs /TC /Od /nologo /c /Gz /Focallee_stdcall.obj callee.c
> cl /FAs /TC /Od /nologo /c /Gz /Focaller_stdcall.obj caller.c
> link /SUBSYSTEM:CONSOLE /NOLOGO /OUT:stdcall.exe caller_stdcall.obj callee_stdcall.obj
> stdcall.exe
foo1() = 20
foo2() = 30
foo3() = 60
foo4() = 100

callee.cのアセンブラ出力(callee.asm)

; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.30729.01 

	TITLE	C:\in_vitro\c\calling_conventions\callee.c
	.686P
	.XMM
	include listing.inc
	.model	flat

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

PUBLIC	_foo1@4
; Function compile flags: /Odtp
; File c:\in_vitro\c\calling_conventions\callee.c
_TEXT	SEGMENT
_a$ = 8							; size = 4
_foo1@4	PROC

; 1    : int foo1(int a) { return a * 2; }

	push	ebp
	mov	ebp, esp
	mov	eax, DWORD PTR _a$[ebp]
	shl	eax, 1
	pop	ebp
	ret	4
_foo1@4	ENDP
_TEXT	ENDS
PUBLIC	_foo2@8
; Function compile flags: /Odtp
_TEXT	SEGMENT
_a$ = 8							; size = 4
_b$ = 12						; size = 4
_foo2@8	PROC

; 2    : int foo2(int a, int b) { return a + b; }

	push	ebp
	mov	ebp, esp
	mov	eax, DWORD PTR _a$[ebp]
	add	eax, DWORD PTR _b$[ebp]
	pop	ebp
	ret	8
_foo2@8	ENDP
_TEXT	ENDS
PUBLIC	_foo3@12
; Function compile flags: /Odtp
_TEXT	SEGMENT
_a$ = 8							; size = 4
_b$ = 12						; size = 4
_c$ = 16						; size = 4
_foo3@12 PROC

; 3    : int foo3(int a, int b, int c) { return a + b + c; }

	push	ebp
	mov	ebp, esp
	mov	eax, DWORD PTR _a$[ebp]
	add	eax, DWORD PTR _b$[ebp]
	add	eax, DWORD PTR _c$[ebp]
	pop	ebp
	ret	12					; 0000000cH
_foo3@12 ENDP
_TEXT	ENDS
PUBLIC	_foo4@16
; Function compile flags: /Odtp
_TEXT	SEGMENT
_a$ = 8							; size = 4
_b$ = 12						; size = 4
_c$ = 16						; size = 4
_d$ = 20						; size = 4
_foo4@16 PROC

; 4    : int foo4(int a, int b, int c, int d) { return a + b + c + d; }

	push	ebp
	mov	ebp, esp
	mov	eax, DWORD PTR _a$[ebp]
	add	eax, DWORD PTR _b$[ebp]
	add	eax, DWORD PTR _c$[ebp]
	add	eax, DWORD PTR _d$[ebp]
	pop	ebp
	ret	16					; 00000010H
_foo4@16 ENDP
_TEXT	ENDS
END

caller.cのアセンブラ出力(caller.asm)

; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.30729.01 

	TITLE	C:\in_vitro\c\calling_conventions\caller.c
	.686P
	.XMM
	include listing.inc
	.model	flat

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

_DATA	SEGMENT
$SG2496	DB	'foo1() = %d', 0aH, 00H
	ORG $+3
$SG2497	DB	'foo2() = %d', 0aH, 00H
	ORG $+3
$SG2498	DB	'foo3() = %d', 0aH, 00H
	ORG $+3
$SG2499	DB	'foo4() = %d', 0aH, 00H
_DATA	ENDS
PUBLIC	_main
EXTRN	_foo4@16:PROC
EXTRN	_foo3@12:PROC
EXTRN	_foo2@8:PROC
EXTRN	_printf:PROC
EXTRN	_foo1@4:PROC
; Function compile flags: /Odtp
; File c:\in_vitro\c\calling_conventions\caller.c
_TEXT	SEGMENT
_argc$ = 8						; size = 4
_argv$ = 12						; size = 4
_main	PROC

; 9    : {

	push	ebp
	mov	ebp, esp

; 10   : 	printf("foo1() = %d\n", foo1(10));

	push	10					; 0000000aH
	call	_foo1@4
	push	eax
	push	OFFSET $SG2496
	call	_printf
	add	esp, 8

; 11   : 	printf("foo2() = %d\n", foo2(10, 20));

	push	20					; 00000014H
	push	10					; 0000000aH
	call	_foo2@8
	push	eax
	push	OFFSET $SG2497
	call	_printf
	add	esp, 8

; 12   : 	printf("foo3() = %d\n", foo3(10, 20, 30));

	push	30					; 0000001eH
	push	20					; 00000014H
	push	10					; 0000000aH
	call	_foo3@12
	push	eax
	push	OFFSET $SG2498
	call	_printf
	add	esp, 8

; 13   : 	printf("foo4() = %d\n", foo4(10, 20, 30, 40));

	push	40					; 00000028H
	push	30					; 0000001eH
	push	20					; 00000014H
	push	10					; 0000000aH
	call	_foo4@16
	push	eax
	push	OFFSET $SG2499
	call	_printf
	add	esp, 8

; 14   : 	return 0;

	xor	eax, eax

; 15   : }

	pop	ebp
	ret	0
_main	ENDP
_TEXT	ENDS
END

Borland C++ Compiler

MinGW/MSYS

OpenWatcom Compiler(16bit)

OpenWatcom Compiler(32bit)

Turbo C++ 4.0J

GCC4.1.2 + binutils-2.7.50.0.6 (CentOS5.2)



プレーンテキスト形式でダウンロード
表示中のバージョン : 2
現在のバージョン : 5
更新者: msakamoto-sf
更新日: 2010-03-19 17:43:15
md5:ffb058cfb4455d0a9c4f461c058395b9
sha1:dadf5232eb4c24b8797d30cc6071697362d8a6f4
コメント
コメントを投稿するにはログインして下さい。