編集部イチオシ

パソコンを回路レベルで自作する (Intel x86 IA-32)

@kaitou_ryaku が一人で作るCPU (x86) の進捗管理用メモ。随時更新。 最新状況(2019/09/21): 自作CPU上の自作OS上でテトリスが動いた 元はこれ https://qiita.com/advent-calendar/2017/lowlayer
173
前へ 1 2 ・・ 5 次へ
解答略 @kaitou_ryaku

FPGAでCPUを自作してて、機械語命令を1つ増やしたいとする。理想としては、その機能に対応するサブルーチン的なのを1つだけ作り、今のCPUにくっつけて実装したい。しかしそれは無理だ。CPUはステージに分割されてて、少なくともデコーダーとALUの二箇所で書き換えが生じる。他にも細々とした修正が入る

2019-07-08 23:12:07
解答略 @kaitou_ryaku

同様の問題がコンパイラの自作でも生じる。新たな構文に対応するには字句解析・構文解析・中間コード生成まで広くて薄い書き換えが必要になる。ステージ間が疎結合で抽象化されてれば書き換えが少なく済む。このCPUとコンパイラの共通性は、どちらもシーケンシャルな言語処理系という本質に起因してる

2019-07-08 23:31:04

2019/07/09 CPUの回路図を分かりやすく描こうとして、紙と鉛筆で10回ぐらい描きなおして、だいぶ整理された。そのおかげで設計がイマイチなところが多数あぶり出された。

あと、ステージ間の情報の受け渡しの図が、おおむね回路図と同じになるという発見があった(よく考えると当たり前である)。なのでステージの遷移が見えるように回路図を描くと分かりやすい(2枚目の図はそのように描かれている)

解答略 @kaitou_ryaku

この画像は、最近自作しているCPU(x86, IA-32)の回路図で、丸印のワイヤー入出力がステージ遷移に対応します。ところで1枚目の画像のようにデザインが酷い回路図を描くと、製作者本人すら訳が分からなくなります。2枚目のように綺麗な回路図を描くのは大変ですが、脳内が整理されるので元が取れます pic.twitter.com/yseeMR1vEm

2019-07-09 00:03:20
拡大
拡大

2019/07/13 x86 (IA-32)の命令セット表をinkscapeで描いた。この時期はIntelのマニュアルpdfを読みまくっていた。その最後の方に命令セット表が載っているのだが、略語だらけで初心者お断り感がものすごい。なので、普段アセンブラのニーモニックだけ触っててバイナリに詳しくない人にも理解しやすい表を描こうと思った。そのためr/mのような表記を避けて、意図的に[M]などと書いている。

ここでの発見として、x86もx64も命令セット表は思った以上に同じで、違いはinc/decのあたりと、push, popの64bit化ぐらいだった

解答略 @kaitou_ryaku

これでも喰らえ!!!Intel-CPU x86命令セット表だ!!!x64で削除されたIA-32の命令は灰色にして、中に新しい命令を書いてやった!!!x86命令セットDeveloper's Manualと格闘して表を書く内に、16進数列を見たらx86のニーモニックが浮かぶようになった。ModRMもSIBも「見える」能力が手に入った!! pic.twitter.com/qqDgjPUX8S

2019-07-13 01:07:58
拡大
解答略 @kaitou_ryaku

x86のコンピュータをHDLで自作しているのだが、HDD(的な何か)を追加するか悩んでいる。追加すれば、ROMにブートローダを載せてHDDから起動できるようになる。その代わりchipsetにIO-Controllerを追加したりHDD読込用の割り込みハンドラを書く手間が増える。面倒だしROMのBIOSだけで動くシステムにしよ

2019-07-14 07:17:04
解答略 @kaitou_ryaku

多くの人々は「コンピュータはOSが無いと動かない」と勘違いしてる気がするが、別になくても動く。コンピューターサイエンスのすべての分野に精通している人にとって、OSは実行パフォーマンスを低下させるだけの無用な存在に過ぎず、ベアメタルで機械語を走らせた方が実行効率上がって嬉しいかもしれん

2019-07-14 08:18:14
解答略 @kaitou_ryaku

Intel x86 (IA-32)の命令セット表を作り直した。お菓子の詰合せみたいで美味しそう pic.twitter.com/xxJXShydCM

2019-07-14 21:04:53
拡大
解答略 @kaitou_ryaku

そもそもはx64の命令セット表を作ろうと思って、Intelのマニュアルを紐解きながら @a4lg さん製作の表に落書きしていたのですが、結局IA-32の0x40-0x4FまでをREX Prefixに変えれば(あとは2進化10進数の廃止とかpushのbit数は64固定とか細々した話しかない)ほぼそのままx64の表になることが分かりました pic.twitter.com/4iBJNpzonR

2019-07-14 21:25:40
拡大

2019/07/17 まじめにUARTを実装する。Senderは割り込みを考えなくて済むので簡単だが、Receiverは本質的に割り込み処理なので難しい。とりあえずSenderだけ実装。この機能を載せれば、自作CPU内部の情報を文字列としてUSB経由で普通のPCに送信できる

解答略 @kaitou_ryaku

CPUからUARTで情報を送信するの、タイミングの問題が難しいな。CPUのクロックがUARTより十分早い場合は簡単なのだが、逆にUARTのクロックの方が早いと、CPUからUARTに渡す送信実行フラグの更新が遅れて同じ文字を何度も送信してしまう。これに対処するのは割と困難だ。困った困った

2019-07-17 20:16:25
解答略 @kaitou_ryaku

CPUよりIOの方がクロック周波数が大きいとか、普通のシステムだと考えられないので大した問題では無いような気がする。しかしハードウェアをデバッグする際に、一時的にクロックを1秒間隔ぐらいにして、物理でステップ実行したくなることがある。そうした時にUARTが使えなくなる。BAUD_RATEを変えるか

2019-07-17 20:21:01
解答略 @kaitou_ryaku

逆にIO(UART)よりCPUの方がクロック周波数が大きい場合は、UARTの使用フラグを割り込みコントローラ経由でCPUの割り込みフラグにつないで、UARTの送信が終わるまでCPUをNOPするような割り込みハンドラを実行することで、普通に対処できる。この正常系だけ実装すれば、大きな問題はない気がしてきた

2019-07-17 20:25:34

2019/07/18 BYTE (8bit) のレジスタを操作する命令を作成。これまでは全て32bitでやっていた。これが結構難しくて、eax→al, esp→ahのような奇妙な対応になっているので、既存のコードに多数の書き換えが発生した。

解答略 @kaitou_ryaku

FPGAで自作中のx86(IA-32)プロセッサ、0x00や0x02といった8bit命令に対応した。と言いたいところだが、少し手抜きをしている。8bitのレジスタ、本当は{al,cl,dl,bl,ah,ch,dh,bh}なのだが、面倒くさいので{al,cl,dl,bl,spl,bpl,sil,dil}みたいになってる。こういうのちゃんとやるの面倒くさいんだよなぁ

2019-07-18 01:11:57

2019/07/19 アドレス計算周りを徹底的に作り込む。このへんの詳細な知識は、Intelのマニュアルを読みつつ、CUI上でニーモニックをアセンブルして逆アセンブラする作業を繰り返すことで会得した。マニュアルだけ読んで理解するのは厳しい感がある

解答略 @kaitou_ryaku

自作中のCPU x86 (IA-32)の進捗ですが、今日はアドレス周りのデコーダーを作り込みました。mod!=2かつr/m=espの場合のSIBの処理(index=espの場合のゼロ処理)と、mod=0かつr/m=ebpの場合の変位アドレス処理を実装して、テストベンチを通しました。こういう地味だけど神経使う作業が多くて精神削られるわ

2019-07-19 03:30:11
解答略 @kaitou_ryaku

この辺の辛さは、x86の機械語と真面目に対話しない限り意識に上らないんだよなぁ。コンパイラを自作する分にはニーモニックだけ見れば済むけど、CPUやエミュレータを自作したり、ハンドアセンブルするとなると、機械語の辛さと正面から向き合わねばならない。なによりIntelの公式マニュアルが結構辛い

2019-07-19 03:35:01
解答略 @kaitou_ryaku

Intelのx86 Instruction pdfを読む際のコツですが、CUIでnasmを叩いてニーモニックを機械語にobjdumpするシェルスクリプトを作って、あらかじめ調べたい対象の挙動を観察してから、最後に確認としてpdfを読むのが効率良い気がしています。いきなりpdfを見ても、多分さっぱりわけわかめで挫折すると思う

2019-07-19 03:38:39
解答略 @kaitou_ryaku

intelの機械語に馴染むための最良の方法は、まずadd命令の挙動を徹底的に知ることだと思う。addにはx86の機械語のエッセンスが詰まっている。可変命令長、オペランドのサイズとオペコードのパリティの関係、ModRM, r/m, R, SIB, r/m=ebpの処理, 0x04と0x05におけるaレジスタの優遇等、気持ち悪さの塊だ

2019-07-19 03:42:46

2019/07/20 これまでBYTE命令とアドレシングを作り込んできたので、ようやくADD命令が完全に動くようになった。ここまでが大変だった

解答略 @kaitou_ryaku

自作中のx86 CPUのADD命令のテストベンチが全て通った。ModRMもdispのサイズ選択も即値のサイズ選択もSIBの分岐もオペランドのサイズもal/ah/eaxの選択もeflagsの更新も、全てIntelの仕様書通りに実装したぞ。さすがに一週間ぐらい掛かったな。今は仕様を理解してるけど、一ヶ月後には全て忘れちゃうな

2019-07-20 07:30:19
解答略 @kaitou_ryaku

ソフトウェアのハードウェアの最大の違いは「空間資源の有限性」だと思う。ソフトでは「足りなくなったらmalloc」という作戦で空間資源を(見かけ上)無限に使える。詐欺の一種だ。しかしハードは物理で、全てのサイズを有限に固定する必要がある。代替として「時間」の無限性を空間に転化してやっていく

2019-07-20 19:48:07
解答略 @kaitou_ryaku

例えばキューが溢れたときに「処理が終わるのを待つ」という作戦は、時間の無限性を空間に転化してる感がある 「ハードにはスタックメモリがある。あれは無限大の空間資源やろ!」という反論が予想されるけど、あれはスタックの使用時(つまりソフトウェア)の話であって、ハードとしては有限だと思う。

2019-07-20 20:00:01
前へ 1 2 ・・ 5 次へ