Memory

アセンブリ問題を解く中で調べたメモ。

メモリ階層について

速度・価格 記憶装置 アクセス時間の目安 容量の目安
▲(速・高) レジスタ(Register) CPUが命令から直接扱う ISAから見えるものは数十本程度
│ L1キャッシュ(SRAM) 約 1 ns(数サイクル) 32〜128 KB(コアごと)
│ L2キャッシュ(SRAM) 約 3〜4 ns(数〜十数サイクル) 512 KB〜数 MB(コアごと)
│ L3キャッシュ(SRAM) 約 10〜20 ns(数十サイクル) 数 MB〜数百 MB(共有)
│ 主記憶(メインメモリ、DRAM) 約 50〜100 ns 8 GB〜64 GB以上
▼(遅・安) 二次記憶(NVMe SSD / HDD) 10 µs〜10 ms 256 GB〜数 TB
アーカイブ記憶(テープなど) 秒〜分 数 TB〜PB

数値はCPUの世代、メモリの種類、アクセスパターンなどで変わる、ざっくりした目安だ。 3.2 GHzなら1周期は約0.31 ns。周期は周波数の逆数だ。DDR4-3200の転送速度を、CPUの3,200 MHzと同一視はできない。 周波数が高くても、すべてのメモリアクセスや演算が同じ割合で速くなるわけではない。

アセンブリ命令は、レジスタ、メモリ、命令に埋め込まれた即値を扱う。CPUは通常、キャッシュとRAMを区別せず同じメモリ空間としてアクセスする。

このページではx86-64のレジスタと呼び出し規約を扱う。ARM64の命令とレジスタはARM64のメモを参照。

x86-64のレジスタ

x86-64の主な汎用レジスタと命令ポインタ:

rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp, r8〜r15, rip

64-bit 全体                  [ RAX ]
32-bit(下位32ビット)       [ EAX ]
16-bit(下位16ビット)       [ AX  ]
 8-bit(AXの上位8ビット)    [ AH  ]
 8-bit(AXの下位8ビット)    [ AL  ]

用途を分ける。EAX、AX、AH、ALは、それぞれRAXの一部を指す。EAXなどへの32ビット書き込みでは、仕様上RAXの上位32ビットが0になる。

主な役割・慣習

レジスタ 主な役割・慣習
rax 整数・ポインタの戻り値(返り値)に使う(ABIによる)
rsp スタックポインタ。スタックの先頭を指すため、通常は自由に使わない
rbp フレームポインタに使うことがある。省略時は汎用レジスタとして使える
rip 次に実行する命令の位置を指す命令ポインタ

引数の渡し先は、x86-64のチップではなくOS・ABI(呼び出し規約)で決まる。

規約 整数・ポインタ引数のレジスタ(左から第1引数)
System V AMD64 ABI(Linux、macOSなど) rdi, rsi, rdx, rcx, r8, r9
Microsoft x64(Windows) rcx, rdx, r8, r9

表を超えた引数は、規約に従ってスタックなどに渡る。Windows x64では、呼び出し側が4つの引数レジスタ用のシャドウ領域も用意する。 浮動小数点引数には別の分類がある。System V AMD64では主にxmm0〜xmm7、Microsoft x64では主にxmm0〜xmm3を使う。構造体の渡し方や戻り値にも別の規則がある。

参考資料