0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Windows x64 と Linux x64 における引数のレジスタ・スタック配置の比較

Posted at

目的

WindowsとLinuxで、引数渡しにどのような違いがあるのかを調べます。

Cソース

gcc -O0 -S -masm=intel test.c -o test.s
test.c
void func(
    char a1, char a2, char a3, char a4,
    char a5, char a6, char a7, char a8,
    char a9, char a10, char a11, char a12
) {
    // 何もしない。
}

int main() {
    // 適当な値を渡して呼び出す
    func(1,2,3,4,5,6,7,8,9,10,11,12);
    return 0;
}

生成されたアセンブリ

Windows10

test.s
test.s
	.file	"test.c"
	.intel_syntax noprefix
	.text
	.globl	func
	.def	func;	.scl	2;	.type	32;	.endef
	.seh_proc	func
func:
	push	rbp
	.seh_pushreg	rbp
	push	r13
	.seh_pushreg	r13
	push	r12
	.seh_pushreg	r12
	push	rdi
	.seh_pushreg	rdi
	push	rsi
	.seh_pushreg	rsi
	push	rbx
	.seh_pushreg	rbx
	sub	rsp, 40
	.seh_stackalloc	40
	lea	rbp, 32[rsp]
	.seh_setframe	rbp, 32
	.seh_endprologue
	mov	eax, edx
	mov	r13d, r8d
	mov	r12d, r9d
	mov	edi, DWORD PTR 96[rbp]
	mov	esi, DWORD PTR 104[rbp]
	mov	ebx, DWORD PTR 112[rbp]
	mov	r11d, DWORD PTR 120[rbp]
	mov	r10d, DWORD PTR 128[rbp]
	mov	r9d, DWORD PTR 136[rbp]
	mov	r8d, DWORD PTR 144[rbp]
	mov	edx, DWORD PTR 152[rbp]
	mov	BYTE PTR 64[rbp], cl
	mov	BYTE PTR 72[rbp], al
	mov	eax, r13d
	mov	BYTE PTR 80[rbp], al
	mov	eax, r12d
	mov	BYTE PTR 88[rbp], al
	mov	eax, edi
	mov	BYTE PTR -4[rbp], al
	mov	eax, esi
	mov	BYTE PTR -8[rbp], al
	mov	eax, ebx
	mov	BYTE PTR -12[rbp], al
	mov	eax, r11d
	mov	BYTE PTR -16[rbp], al
	mov	eax, r10d
	mov	BYTE PTR -20[rbp], al
	mov	eax, r9d
	mov	BYTE PTR -24[rbp], al
	mov	eax, r8d
	mov	BYTE PTR -28[rbp], al
	mov	eax, edx
	mov	BYTE PTR -32[rbp], al
	nop
	add	rsp, 40
	pop	rbx
	pop	rsi
	pop	rdi
	pop	r12
	pop	r13
	pop	rbp
	ret
	.seh_endproc
	.globl	main
	.def	main;	.scl	2;	.type	32;	.endef
	.seh_proc	main
main:
	push	rbp
	.seh_pushreg	rbp
	mov	rbp, rsp
	.seh_setframe	rbp, 0
	sub	rsp, 96
	.seh_stackalloc	96
	.seh_endprologue
	call	__main
	mov	DWORD PTR 88[rsp], 12
	mov	DWORD PTR 80[rsp], 11
	mov	DWORD PTR 72[rsp], 10
	mov	DWORD PTR 64[rsp], 9
	mov	DWORD PTR 56[rsp], 8
	mov	DWORD PTR 48[rsp], 7
	mov	DWORD PTR 40[rsp], 6
	mov	DWORD PTR 32[rsp], 5
	mov	r9d, 4
	mov	r8d, 3
	mov	edx, 2
	mov	ecx, 1
	call	func
	mov	eax, 0
	add	rsp, 96
	pop	rbp
	ret
	.seh_endproc
	.def	__main;	.scl	2;	.type	32;	.endef
	.ident	"GCC: (MinGW-W64 x86_64-ucrt-posix-seh, built by Brecht Sanders, r4) 15.1.0"

Ubuntu

test.s
test.s
	.file	"test.c"
	.intel_syntax noprefix
	.text
	.globl	func
	.type	func, @function
func:
.LFB0:
	.cfi_startproc
	endbr64
	push	rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	mov	rbp, rsp
	.cfi_def_cfa_register 6
	push	r13
	push	r12
	push	rbx
	.cfi_offset 13, -24
	.cfi_offset 12, -32
	.cfi_offset 3, -40
	mov	eax, ecx
	mov	r13d, r8d
	mov	r12d, r9d
	mov	ebx, DWORD PTR 16[rbp]
	mov	r11d, DWORD PTR 24[rbp]
	mov	r10d, DWORD PTR 32[rbp]
	mov	r9d, DWORD PTR 40[rbp]
	mov	r8d, DWORD PTR 48[rbp]
	mov	ecx, DWORD PTR 56[rbp]
	mov	BYTE PTR -28[rbp], dil
	mov	BYTE PTR -32[rbp], sil
	mov	BYTE PTR -36[rbp], dl
	mov	BYTE PTR -40[rbp], al
	mov	eax, r13d
	mov	BYTE PTR -44[rbp], al
	mov	eax, r12d
	mov	BYTE PTR -48[rbp], al
	mov	eax, ebx
	mov	BYTE PTR -52[rbp], al
	mov	eax, r11d
	mov	BYTE PTR -56[rbp], al
	mov	eax, r10d
	mov	BYTE PTR -60[rbp], al
	mov	eax, r9d
	mov	BYTE PTR -64[rbp], al
	mov	eax, r8d
	mov	BYTE PTR -68[rbp], al
	mov	eax, ecx
	mov	BYTE PTR -72[rbp], al
	nop
	pop	rbx
	pop	r12
	pop	r13
	pop	rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	func, .-func
	.globl	main
	.type	main, @function
main:
.LFB1:
	.cfi_startproc
	endbr64
	push	rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	mov	rbp, rsp
	.cfi_def_cfa_register 6
	push	12
	push	11
	push	10
	push	9
	push	8
	push	7
	mov	r9d, 6
	mov	r8d, 5
	mov	ecx, 4
	mov	edx, 3
	mov	esi, 2
	mov	edi, 1
	call	func
	add	rsp, 48
	mov	eax, 0
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE1:
	.size	main, .-main
	.ident	"GCC: (Ubuntu 11.4.0-1ubuntu1~22.04.2) 11.4.0"
	.section	.note.GNU-stack,"",@progbits
	.section	.note.gnu.property,"a"
	.align 8
	.long	1f - 0f
	.long	4f - 1f
	.long	5
0:
	.string	"GNU"
1:
	.align 8
	.long	0xc0000002
	.long	3f - 2f
2:
	.long	0x3
3:
	.align 8
4:

WindowsとLinuxの違いを比較

項目 Windows x64 Linux x64
レジスタに入る引数 4個 6個
使用レジスタ RCX, RDX, R8, R9 RDI, RSI, RDX, RCX, R8, R9
残りの引数 スタック スタック

Windows

	mov	DWORD PTR 88[rsp], 12
	mov	DWORD PTR 80[rsp], 11
	mov	DWORD PTR 72[rsp], 10
	mov	DWORD PTR 64[rsp], 9
	mov	DWORD PTR 56[rsp], 8
	mov	DWORD PTR 48[rsp], 7
	mov	DWORD PTR 40[rsp], 6
	mov	DWORD PTR 32[rsp], 5
	mov	r9d, 4
	mov	r8d, 3
	mov	edx, 2
	mov	ecx, 1

Linux

	push	12
	push	11
	push	10
	push	9
	push	8
	push	7
	mov	r9d, 6
	mov	r8d, 5
	mov	ecx, 4
	mov	edx, 3
	mov	esi, 2
	mov	edi, 1

動作環境

Windows

OS: Windows10
Version: 10.0.19045.6332
CPU: Intel Core i7-10750H, 6 cores, 12 threads
GCC: 15.1.0 (MinGW-W64 x86_64-ucrt-posix-seh, built by Brecht Sanders, r4)
Architecture: x86_64

Ubuntu

OS: Ubuntu 22.04.5 LTS (Jammy Jellyfish)
Kernel: Linux 6.8.0-84-generic
CPU: Intel Core i5-8250U, 4 cores, 8 threads, Little Endian
GCC: 12.3.0
Architecture: x86_64

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?