書籍の補足情報
書籍の内容について,出版後に気がついた点などをその都度追記していきます.
■ 最初に説明するアーキにPowerPCを選んだ理由 (2014/10/04)
最初に扱うアーキは,以下の基準で選びました.
- 現行のアーキテクチャであること.
- 最初に扱うアーキが「今は見ることは無いアーキです」とか言っちゃった
瞬間に初心者はモチベーションを失うと思う(なぜなら私がそうだから)ので,
最初に扱うアーキは現行のものにすることは必須かと思った.
- RISCで癖が少なく,読みやすいこと.
- 癖が少ないというのはISA全体としてということではなく,sample.cを説明する
ために,あくまでsample.cのアセンブリの,とくに先頭のあたりを見る限り
では,ということです.
- ARMは癖があるので却下.
最初に説明するのは,メジャーだからそれにしたというものでなく,
アセンブラを初心者に説明しやすいか?という観点で選ぶべきと思った.
(アセンブラの本なのだから,アセンブラの観点で選ぶべきと思った)
- 読みやすいという点でVAXやPDP-11などのCISC系から始める案も無くは無かったが,
現行でないという点で初心者がモチベーション持って読み始められないと思い却下.
この点でMIPSとPowerPCが候補だったのですが(そして個人的にはぜひMIPSにしたかった
のですが),MIPSは以下の点で追加説明が必要になるので,最初は説明が極力少なく
済むもの,ということでPowerPCを選択しました.
(PowerPCで基本を説明したあとに,MIPSで追加として以下を説明する,という流れに
して一度に説明することを減らしたほうが,初心者が混乱しないと思った)
- 遅延スロットがある
- ゼロレジスタを持っている
- 標準的なアセンブラで,レジスタ名がv0やa0など,種類別になっている.
(PowerPCは単純な通番)
- グローバルポインタが標準的に使われる
■ SHのPC相対について (2014/10/04)
※ 本件は,電子書籍版にて修正しました (2015/07/06)
PC相対によるメモリアクセスの際に,PCの値が4バイトアラインメントされて
いるという記述がありますが,すみませんちょっと筆者の勘違いが残ってしまって
いたようです.(情けない…)
sh-elf.dを実際に見てみたところ,以下のようになっているようです.
- PC(プログラムカウンタ)は,2つ先の命令(つまり当該の命令から+4バイトの位置)を指している.
- mov.wで2バイトをPC相対でロードする際には,
「PC+イミディエイト値×2」のようにしてアドレスを計算している.
(2の倍数で単純に加算するだけ)
- mov.lで4バイトをPC相対でロードする際には,PCを4バイトアラインメント
して,さらにイミディエイト値×4を加算することでアドレスを計算している.
つまり「(PC & ~3)+イミディエイト値×4」のようにアドレスを計算している.
(4バイトロードなので,アラインメントされる)
→ アラインメントは「切捨て」によって行われています.
これはCPUの回路的には,「下位2ビットを無視する」ことで実現できます.
(七誌さんの指摘
で注意書きを追加し説明を詳細にしました(2014/12/18).七誌さんありがとうございます!)
わりと大きな間違いが残ってしまいすみません.校正は頑張ったのですが,
SHの章はわりと早い時期に書いていた部分なので,チェック漏れでそのまま
残ってしまったようです.増刷などで修正の機会があれば直したいです.
■ PA-RISCの遅延スロットの扱いについて (2014/10/04)
※ 本件は,電子書籍版にて注意書きを入れました (2015/07/06)
書籍中で「PA-RISCでは遅延スロットの有無を選べる」とありますが,
どうも「Nullification」というPA-RISC特有の機能で,
後続の命令を条件次第でスキップできる,というもののようです.
詳しくはネットで検索してみると,さらに詳しい情報が得られるかと.
■ 各アーキテクチャのエンディアンについて (2014/10/05)
書籍中では各アーキテクチャのエンディアンは,
「このアーキはビッグ,このアーキはリトル」みたいにして
決めうちにして説明しています.
が,実際には両エンディアンに対応しているアーキテクチャも多いです.
そういうのは「バイエンディアン」と言います.
動的に切り替えて使えるようなプロセッサも多いです.
で,それでも普通は「標準的にはこっちのエンディアンで使われることが多い」
というのがアーキテクチャごとにあったりもするのですが,分野によってその
「標準的なエンディアン」が異なっているアーキテクチャもあったりします.
例えばMIPSはリトルエンディアンとビッグエンディアンの両方がありますが,
ワークステーション用に利用される場合はリトル,組込み系で利用される場合は
ビッグが標準,みたいになっています.ああややこしい.
そしてgcc側では,これらはgccのビルド時に指定できたりもします
(例えば「mipseb」みたいにしてアーキ名に「eb」とかついたらビッグエンディアン,
「mipsel」みたいに「el」がついたらリトルエンディアンを示していたりします).
が,書籍中ではgccを標準的にビルドしたときのエンディアンを,
そのアーキの標準的なエンディアンとして扱っています.
■ x86-64のred zoneについて (2015/01/04)
※ 本件は,電子書籍版にて注意書きを入れました (2015/07/06)
p.393のx86-64の解説で,スタック上の獲得していない部分を利用しているという
記述がありますが,x86-64のABIで定義されている「red zone」というものの動作の
ようです.
(サイボウズラボの竹迫良範さんより情報をいただきました.
竹迫さん,ありがとうございました!)
red zone ですが,軽く調べてみたところ,
スタックポインタを越えて未獲得の部分を利用する,というもののようです
(ていうかその未獲得の部分を「red zone」と呼ぶ).
スタックポインタの加減算を避けることで命令の依存性を少なくし,
パイプラインが効率的に動作するようにする(もしくは最適化をしやすくする?)
ためのもののようです.
コンパイラの機能であり,gccでは以下で抑止することができるようです.
-mno-red-zone
以下,man gcc より引用です.
-mno-red-zone
Do not use a so called red zone for x86-64 code. The red zone is
mandated by the x86-64 ABI, it is a 128-byte area beyond the loca-
tion of the stack pointer that will not be modified by signal or
interrupt handlers and therefore can be used for temporary data
without adjusting the stack pointer. The flag -mno-red-zone dis-
ables this red zone.
要約すると,以下のようなことが書いてあります.
- 「スタックポインタを越えた位置にある128バイト領域」
- 「シグナル処理や割込みハンドラによって破壊されない」
- 「スタックポインタの加減算無しにテンポラリデータを置くために利用できる」
疑問点は,割込みハンドラで破壊されないということがどのようにして保証されて
いるのかですが,OSの割込みハンドラのほうで,スタックは128バイト減算してから
利用するというような考慮がされているのかなあ…とか推測しています.
(あくまで推測ですが)
■ cross-20130826 でのM・COREの不備について (2015/10/22)
シミュレータ動作のためのサンプルプログラムで,
M・COREのスタートアップに不備があることが判明しました.
現状,スタックポインタであるR0の設定が行われておらず,
GDBシミュレータが初期化時に設定したスタックポインタのまま動作しています.
(動作に実害があるわけではありませんが,他のアーキテクチャでの実装と
食い違っています)
cross/exec/lib-mcore-elf.S に以下の修正を入れることで,他のアーキテクチャと
同様に,リンカスクリプトで指定されているスタック位置がスタックポインタに
設定されるようになります.
.globl _start
.type _start, @function
_start:
lrw r7, _estack
+ mov r0, r7
jsri main
■ 誤記など
- 以下は「熱血!」の電子書籍版にて修正しました (2015/07/06)
- p.119下から7行目 「fe1422」→「fe1420」 (2015/01/03)
- p.231下から3行目 「2バイト」→「3バイト」 (2015/01/03)
- 以下は大熱血!アセンブラ入門で修正しました (「熱血!」の電子書籍版では未修正) (2017/10/28)
- 以下は未修正です
- p.126上から17行目 「-127〜128の間」→「-128〜127の間」 (2017/10/28)
- p.506 リスト17.5 return_short_size()/return_long_size() のリストに
なっているが,return_short()/return_long() のリストが正しい (2017/11/21)
メールは kozos(アットマーク)kozos.jp まで