「X86」の版間の差分
提供: Wikinote
細 |
(→64 ビットモード) |
||
行25: | 行25: | ||
; 32 ビット | ; 32 ビット | ||
: EAX, EBX, ECX, EDX, EDI, ESI, EBP, ESP, R8D - R15D | : EAX, EBX, ECX, EDX, EDI, ESI, EBP, ESP, R8D - R15D | ||
+ | |||
+ | ところで、32 ビット OS でも <code>long long int</code> を定義すると 8 バイトの整数が定義できるが、 | ||
+ | これはどのように処理されているのだろうか?実験してみた。 | ||
+ | [hagio@lab ~]$ cat > 64bit.c | ||
+ | int main(void) { | ||
+ | long long int s64; | ||
+ | s64 = 0x1000000000000000LL; | ||
+ | return 0; | ||
+ | } | ||
+ | [hagio@lab lab]$ cc -S 64bit.c | ||
+ | [hagio@lab lab]$ cat 64bit.s | ||
+ | .file "64bit.c" | ||
+ | .text | ||
+ | .globl main | ||
+ | .type main, @function | ||
+ | main: | ||
+ | leal 4(%esp), %ecx | ||
+ | andl $-16, %esp | ||
+ | pushl -4(%ecx) | ||
+ | pushl %ebp | ||
+ | movl %esp, %ebp | ||
+ | pushl %ecx | ||
+ | subl $20, %esp | ||
+ | ★movl $0, -16(%ebp) | ||
+ | ★movl $268435456, -12(%ebp) | ||
+ | movl $0, %eax | ||
+ | addl $20, %esp | ||
+ | popl %ecx | ||
+ | popl %ebp | ||
+ | leal -4(%ecx), %esp | ||
+ | ret | ||
+ | .size main, .-main | ||
+ | .ident "GCC: (GNU) 4.1.2 20071124 (Red Hat 4.1.2-42)" | ||
+ | .section .note.GNU-stack,"",@progbits | ||
+ | 単に 2 回に分けてメモリに格納しているようだ。64 ビット OS だとどうなるんだろう… 気になる。 | ||
=== セグメントレジスタ === | === セグメントレジスタ === |
2009年4月23日 (木) 22:43時点における版
そのうちアセンブリ言語も読まなきゃならなくなりそうなので。
参考文献
- Intel® 64 and IA-32 Architectures Software Developer's Manuals
- Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 1: Basic Architecture
レジスタ
汎用レジスタ
これらは 32 ビットである。'E' を省いたものが下位 16 ビットを示す。 また、A - D までは、?L で下位 0-7 ビット、?H で 下位 8-15 ビットを示す。
- EAX — Accumulator for operands and results data
- EBX — Pointer to data in the DS segment
- ECX — Counter for string and loop operations
- EDX — I/O pointer
- ESI — Pointer to data in the segment pointed to by the DS register; source pointer for string operations
- EDI — Pointer to data (or destination) in the segment pointed to by the ES register; destination pointer for string operations
- ESP — Stack pointer (in the SS segment)
- EBP — Pointer to data on the stack (in the SS segment)
64 ビットモード
64 ビットモードでは、以下の 16 個の汎用レジスタが利用できる。 これらはそれぞれ、32 ビットでアクセスすることも可能だ。
- 64 ビット
- RAX, RBX, RCX, RDX, RDI, RSI, RBP, RSP, R8 - R15
- 32 ビット
- EAX, EBX, ECX, EDX, EDI, ESI, EBP, ESP, R8D - R15D
ところで、32 ビット OS でも long long int
を定義すると 8 バイトの整数が定義できるが、
これはどのように処理されているのだろうか?実験してみた。
[hagio@lab ~]$ cat > 64bit.c int main(void) { long long int s64; s64 = 0x1000000000000000LL; return 0; } [hagio@lab lab]$ cc -S 64bit.c [hagio@lab lab]$ cat 64bit.s .file "64bit.c" .text .globl main .type main, @function main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $20, %esp ★movl $0, -16(%ebp) ★movl $268435456, -12(%ebp) movl $0, %eax addl $20, %esp popl %ecx popl %ebp leal -4(%ecx), %esp ret .size main, .-main .ident "GCC: (GNU) 4.1.2 20071124 (Red Hat 4.1.2-42)" .section .note.GNU-stack,"",@progbits
単に 2 回に分けてメモリに格納しているようだ。64 ビット OS だとどうなるんだろう… 気になる。
セグメントレジスタ
すべて 16 ビット幅である。
- CS — Code segment register
- DS, ES, FS, GS — Data segment register
- SS — Stack segment register
フラグレジスタ
- EFLAGS
- 32 ビット幅で、プロセッサ初期化後の値は 0x00000002 となる。
ステータスフラグ
- CF (bit 0) — Carry flag
- PF (bit 2) — Parity flag
- AF (bit 4) — Adjust flag
- ZF (bit 6) — Zero flag
- SF (bit 7) — Sign flag
- OF (bit 11) — Overflow flag
フラグは多すぎて面倒なのでまたやる気が出たら…
命令ポインタ
- EIP (RIP)
- 32 ビット幅 (64 ビット幅)