KDOC 449: 32bitマシンでint64型を使うとどうなるのか?
この文書のステータス
- 作成
- 2025-10-12 貴島
- レビュー
- 2025-10-17 貴島
概要
32bitマシンだとレジスタに入り切らないため1度で処理できず、スタックを使う想定だが、正しいだろうか。レジスタよりサイズが大きい場合にどう扱うか、ともいえる。
32bit/64bitでコンパイルして、アセンブリのdiffを見る。
tmpfile=$(mktemp /tmp/tmp.XXXXXX.c)
cat > $tmpfile <<EOF
#include <stdio.h>
int main() {
long long a = 1234567890123;
int b = 42;
printf("%lld %d\n", a, b);
return 0;
}
EOF
docker run --rm -v /tmp:/tmp -w /tmp i386/ubuntu bash -c "apt update -y && apt install -y build-essential && gcc -m32 -S $tmpfile -o 32.s && cat 32.s"
rm $tmpfile
tmpfile=$(mktemp /tmp/tmp.XXXXXX.c)
cat > $tmpfile <<EOF
#include <stdio.h>
int main() {
long long a = 1234567890123;
int b = 42;
printf("%lld %d\n", a, b);
return 0;
}
EOF
gcc -S $tmpfile -o /tmp/64.s
rm $tmpfile
cat /tmp/32.s
cat /tmp/64.s
diff /tmp/32.s /tmp/64.s
.file "tmp.Q8B7li.c"
.text
.section .rodata
.LC0:
.string "%lld %d\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
leal 4(%esp), %ecx
.cfi_def_cfa 1, 0
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
.cfi_escape 0x10,0x5,0x2,0x75,0
movl %esp, %ebp
pushl %ebx
pushl %ecx
.cfi_escape 0xf,0x3,0x75,0x78,0x6
.cfi_escape 0x10,0x3,0x2,0x75,0x7c
subl $16, %esp
call __x86.get_pc_thunk.ax
addl $_GLOBAL_OFFSET_TABLE_, %eax
movl $1912276171, -16(%ebp)
movl $287, -12(%ebp)
movl $42, -20(%ebp)
pushl -20(%ebp)
pushl -12(%ebp)
pushl -16(%ebp)
leal .LC0@GOTOFF(%eax), %edx
pushl %edx
movl %eax, %ebx
call printf@PLT
addl $16, %esp
movl $0, %eax
leal -8(%ebp), %esp
popl %ecx
.cfi_restore 1
.cfi_def_cfa 1, 0
popl %ebx
.cfi_restore 3
popl %ebp
.cfi_restore 5
leal -4(%ecx), %esp
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .-main
.section .text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat
.globl __x86.get_pc_thunk.ax
.hidden __x86.get_pc_thunk.ax
.type __x86.get_pc_thunk.ax, @function
__x86.get_pc_thunk.ax:
.LFB1:
.cfi_startproc
movl (%esp), %eax
ret
.cfi_endproc
.LFE1:
.ident "GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"
.section .note.GNU-stack,"",@progbits
.file "tmp.wWxeed.c"
.text
.section .rodata
.LC0:
.string "%lld %d\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movabsq $1234567890123, %rax
movq %rax, -8(%rbp)
movl $42, -12(%rbp)
movl -12(%rbp), %edx
movq -8(%rbp), %rax
movq %rax, %rsi
leaq .LC0(%rip), %rax
movq %rax, %rdi
movl $0, %eax
call printf@PLT
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.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:
1c1
< .file "tmp.Q8B7li.c"
---
> .file "tmp.wWxeed.c"
12,34c12,27
< leal 4(%esp), %ecx
< .cfi_def_cfa 1, 0
< andl $-16, %esp
< pushl -4(%ecx)
< pushl %ebp
< .cfi_escape 0x10,0x5,0x2,0x75,0
< movl %esp, %ebp
< pushl %ebx
< pushl %ecx
< .cfi_escape 0xf,0x3,0x75,0x78,0x6
< .cfi_escape 0x10,0x3,0x2,0x75,0x7c
< subl $16, %esp
< call __x86.get_pc_thunk.ax
< addl $_GLOBAL_OFFSET_TABLE_, %eax
< movl $1912276171, -16(%ebp)
< movl $287, -12(%ebp)
< movl $42, -20(%ebp)
< pushl -20(%ebp)
< pushl -12(%ebp)
< pushl -16(%ebp)
< leal .LC0@GOTOFF(%eax), %edx
< pushl %edx
< movl %eax, %ebx
---
> endbr64
> pushq %rbp
> .cfi_def_cfa_offset 16
> .cfi_offset 6, -16
> movq %rsp, %rbp
> .cfi_def_cfa_register 6
> subq $16, %rsp
> movabsq $1234567890123, %rax
> movq %rax, -8(%rbp)
> movl $42, -12(%rbp)
> movl -12(%rbp), %edx
> movq -8(%rbp), %rax
> movq %rax, %rsi
> leaq .LC0(%rip), %rax
> movq %rax, %rdi
> movl $0, %eax
36d28
< addl $16, %esp
38,47c30,31
< leal -8(%ebp), %esp
< popl %ecx
< .cfi_restore 1
< .cfi_def_cfa 1, 0
< popl %ebx
< .cfi_restore 3
< popl %ebp
< .cfi_restore 5
< leal -4(%ecx), %esp
< .cfi_def_cfa 4, 4
---
> leave
> .cfi_def_cfa 7, 8
52,63c36
< .section .text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat
< .globl __x86.get_pc_thunk.ax
< .hidden __x86.get_pc_thunk.ax
< .type __x86.get_pc_thunk.ax, @function
< __x86.get_pc_thunk.ax:
< .LFB1:
< .cfi_startproc
< movl (%esp), %eax
< ret
< .cfi_endproc
< .LFE1:
< .ident "GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"
---
> .ident "GCC: (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0"
64a38,53
> .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:
関連
抽象。
- 一度に扱える幅を超える値は、幅に収まる複数の断片に分けて扱う
関連。
- 類推: ビット幅が違う場合にどういった違いが出るか調べる
- 前提: KDOC 313: CPUのビット数はレジスタのサイズである。処理単位の大きさが何で決まるかの前提