ワード: CPUが一回のアクセスで取り扱うデータの最大サイズ(だいたいデータバスの幅と同じ)
- 32bitなら1ワード=4byteでレジスタ長は32bit
- 互換性の担保のために、Intel系では1ワード2byteにしている場合も(4byte: ダブルワード、8byte: クワッドワードでクワッドをよく使う)
アライメント制約
CPUがアクセスするときのためにワードの先頭アドレスがワード長の倍数でないといけないという制約
これを破ると例外が起きるか、二回に分けてアクセスして複合するため時間がかかってしまう
Segmentation Faultとか、ハードウェア側でOSにエラーを投げて強制的に停止する
データバスとレジスタの一対一対応を担保することで高速化を図るための制約(これが担保されていないと各バイトをレジスタのどの位置にも送れる仕組みや複数回のアクセスをして並び替えを行うような仕組みが必要になる)
エンディアン
二バイト以上のサイズ単位でメモリにデータを格納するときにバイトとアドレスをどう対応させる?
- ビッグエンディアン(最上位から順に振る)
- リトルエンディアン(最下位から順に振る)
基本的にはどっちでも問題ない
ビッグエンディアン
| A | A+1 | A+2 | A+3 |
|---|---|---|---|
| 12 | 34 | 56 | 78 |
リトルエンディアン
| A | A+1 | A+2 | A+3 |
|---|---|---|---|
| 78 | 56 | 34 | 12 |
どちらにせよワード単位で取り出すときにうまくいくので問題ない
→問題はハーフなどで読みだすとき
ディスクへの書き込みはバイト単位
バイト単位のストアであればどのストア方法でも結果は変わらない
問題は格納と読み出しのサイズ単位が違うとき
アセンブリ
どうしてアセンブリを学ぶ?
ffmpegにコントリビュートするため?- 計算機の仕組みを理解するための手段
- 高級言語でCPUの仕組みを考えるのは難しい
- 各階層をそれなりに知っておくことが必要
- SW/HWの理解のために必要
MIPS
- RISCの代表的なCPU
- 32bit/64bit
- かつてはUNIXやスパコン、ゲーム機や組み込みで使用された
- 現在は主流ではないが、教育目的には向いている
- ヘネシーとパターソンの本
- レジスタは
$0から$31までの32本- 0は0固定
- 31はjal(jump and link)が使用
- 残りはソフトウェア的に決められた用途がある
SPIM
- 32bitMIPSのシミュレーター(MIPSの逆順)
- 簡単なシステムコールを扱える
呼び出し規約
- レジスタやメモリは広域変数のようにどこからでも読み書きできる
- ソフトウェア的に制限することによってより安全に
- 関数の呼び出し方法の統一規則
- 引数の渡し方
- 受け取り方
- 返り血の返し方と受け取り方
- スタックの扱い方
- 各レジスタの用途と退避の規則
レジスタの使い方についての規則
- レジスタを局所変数の代わりにしたい
- 関数ごとに使用するレジスタを分離する?
- これだとすぐに枯渇してしまう
- →複数の関数で同じレジスタを使いまわす
- ところで、同一のレジスタを使う関数同士の呼び出しは?
- レジスタの値を一度どこかに退避する必要
- caller-saveレジスタ
- 関数の中で何の準備もなく使用/変更できるがほかの関数を呼び出すと破壊される可能性がある
- callee-saveレジスタ
- ほかの関数を呼び出したも値が破壊されないレジスタ。このレジスタを使用したり変更するためには元の値をどこかへ退避してから使用して元に戻す必要がある
- 関数ごとに使用するレジスタを分離する?