目的
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