2020年の終わりに、コンピューターとは何かについて話します

作成者:カランカラン
💡

質問やフィードバックがありましたら、フォームからお願いします

本文は台湾華語で、ChatGPT で翻訳している記事なので、不確かな部分や間違いがあるかもしれません。ご了承ください

背景

2020年は混乱の年であり、同時に私がコンピュータの本質を再考するきっかけとなった年でもありました。この年、私は自分の得意でない分野に多くの挑戦をし、基本的には「基礎を再認識する」というテーマに沿っていました。

高校(正確には高等職業学校)では電子工学を学んでおり、進学が主流の時代において、実習の授業があったにも関わらず、実際のところは型通りの授業が多く、大半の時間は勉強や問題解決に費やされていました。唯一、幸運だったのは、課業が一般的な高校よりもそれほど重くなかったことです。そうでなければ、私は台科(台北科技大学)に合格することも難しかったでしょう。

高職での経験の中で少し残念だったのは、実際に手を動かすことへの興味があまりなかったことです。多くの時間は、はんだ付けやブレッドボードの配線、配線が重ならないようにすること、ジャンプワイヤーを使わないことなどを教えられましたが、私のように手先が不器用な人間には本当に苦手なことでした。

実際、電子工学を学んでいた頃、自分自身にあまり興味がなかったため、後にプログラミングで生計を立てることになるとは予想していませんでした。しかし、その経験があったからこそ、最近では底層のものに対して興味を持ち始めています。

この問題に戻ると、その答えはコンピュータに対する理解の深さによって決まります。ダイオードやトランジスタ、レジスタ、CPUの動作、オペレーティングシステムなど、各分野の知識は一生をかけても探求しきれないほど深いものです。実際、とても奥が深いです。

私にとって、今年はコンピュータとは何かをしっかり理解する年です。専門家ではありませんが、その中で多くの楽しさを見出し、同時に会社で同じく底層に興味を持つ同僚も見つけました。

電子工学との重なり

高職で電子工学の関連知識を学んでいたとき、これらの知識が後にそれほど役に立つとは思っていませんでした。例えば、ブリッジ整流器、ダイオード、フィルター、安定化などは、充電器でよく使われる回路です。これらのことは試験で何百回も計算しましたし、実習の授業ではブリッジ整流回路の実験を行うこともありました。

CPUの加算では加算器を実装する必要があり、これには半加算器、全加算器が含まれます。これらも授業で真理値表を段階的に学び、論理ゲートを使ってブレッドボード上で一歩一歩実装していくものでした(もちろん、ICを使うこともできます)。

CPUの動作にはクロックが必要で、一般的には水晶振動子を使用するか、別のクロック生成器を接続します。驚いたことに、当初は難解に感じたNE555回路がCPUの動作に必要なクロックを生成できることに気づきました!(もちろん、今ではほとんどが内蔵されています)

当初は理解できなかったフリップフロップが、実際にはレジスタの基本を実装していることに気づきました。基礎を理解するにつれて、これらの知識は高職の時にすでに経験済みであったことに気がつきました。ただ、その時には知識をつなげることができなかっただけなのです。

これらの底層に関わる知識には神秘的な魅力があります。一方で、参入障壁が比較的高いことも事実です。誰もが毎日チップを買ってブレッドボードに接続するわけではなく、各知識点についてある程度の理解が必要です。また、インターネット上には十分な情報がないため、キーワード検索をしても、特定のフォーラムの下のx番目のコメントに答えがあることを発見するまで時間がかかることが多く、自分自身で問題を解決しなければならないことが多いです。

基礎に戻る

これを踏まえ、2020年のテーマはできるだけ底層に近づくことです。ハードウェアであったり、オペレーティングシステムの動作であったり、プログラミング言語の運用を理解したり、いずれにしても底層を理解することができるものです。

そこで、今年の初めにArduinoを購入しました。中には「Arduinoは単に他人が作ったものを使うだけではないか?」と思う人もいるかもしれませんが、確かにその通りです。しかし、私はこの第一歩から始めたいと思っています。あるセンサーについては、他人が用意したライブラリを使わずに、データシートを見てどう使うかを考え、もし本当にうまくいかなければライブラリの実装を確認することにします。

今年の7月には、ArduinoとESP32を使って空気品質監視アプリケーションを実装しました。ここでは、MQTT、DHT11、MH-Z14Aを使用し、データ通信部分にはUARTを利用しました。ライブラリを使うのではなく、MH-Z14Aに関してはデータシートをしっかり読み、実装を行いました。Wi-FiとMQTTの部分はライブラリをそのまま使用しましたが、私にとっては多くのことを学ぶことができました。

これだけでは不十分だと感じ、Arduinoのケースに邪魔されることなく進めたいと思いました。そこで、Amazonで伝説のMOS 6502を探しました。

MOS 6502がクラシックな理由は、その価格が非常に安く、性能も比較的優れているため、FamicomやApple IIなどがこの8ビットCPUを採用しているからです。また、現代のCPUに比べて、その命令セットや設計は非常にシンプルであるため、CPUの動作をより理解しやすいです。

最初は興奮して注文し、その到着を待ちましたが、後になってMOS 6502には内蔵EEPROMがないことに気づきました。プログラムをEEPROMに書き込み、その後MOS 6502に読み取らせる必要があります。しかし、現在日本では私が欲しいEEPROMを入手するための良いルートがないため、この道は一時中止となりました。

代わりにAVRを選びました。私が住んでいる場所の近くには電子部品店があり、atmegaシリーズのマイコンが販売されていました。そのため、いくつか(ATMEGA328、ちょうどArduino UNOで使用されているMCU)を適当に選びました。

ATMEGA328の利点は、第一にその大きさがちょうどブレッドボードに収まること、次にその命令セットが比較的シンプルであること、さらにAVR特有の利点がいくつかあります。例えば:

  • 32個のレジスタがあり、他のアーキテクチャに比べて非常に多い(x86: 8個、ARM: 16個)
  • 大部分の命令が1クロックで実行される
  • ほとんどのAVRチップにはフラッシュメモリとEEPROMが内蔵されており、別途EEPROMを用意する必要がなく、読み取り効率も向上する

アセンブリ言語、ハードウェアロジックの理解

ハードウェアの世界では、すべてが非常にシンプルになり、逆に不便に感じます。例えば、特定のピンを高電位で出力したい場合、純粋なアセンブリ言語(AVR)で書くと、次のようになります:

ldi r16, 0x01
out DDRB, r16
out PORTB, r16

まず、0x01をr16というレジスタに置き、次にDDRBレジスタ(データ方向)を0x01に設定し、PORTB0x01に設定しています。これは実際にはdigitalWriteと非常に似たことをしています。

意外にも、アセンブリ言語は思っていたほど難しくありませんでしたが、業界レベルのアセンブリ言語を書くのは難しいだろうと思います。

割り込み(Interrupt)の深層理解

私はまだ割り込み機構がどのように機能するのかを完全には理解していません(ハードウェア回路を含めて)、しかし、割り込み(Interrupts)に対する理解は深まりました。

一般的なCPUでは、割り込みベクタが定義されており、割り込みが発生したときにCPUが何をすべきかを示しています。割り込みの有無は通常、SREGのグローバル割り込みイネーブルビットによって判断されます。これにはレジスタ操作とビットシフトに十分な理解が必要であり、AVRでは通常、いくつかの関数が対応しています(avr/interrupt.h)。

この部分は非常に興味深いですが、問題が発生しやすいです。もしおもちゃのプロジェクトであれば良いですが、皆さんが本番環境でどのように割り込み機構を管理し、デバッグしているのかは分かりません。

オペレーティングシステムの理解

今年の3月から4月にかけて、Courseraで断続的に視聴していたオペレーティングシステムのコースでは、PC(プログラムカウンタ)、IR(命令レジスタ)、カーネルモード、ユーザーモード、アトミック、スレッドを理解し、信号量(セマフォ)に至るまで学びましたが、実装についてはまだ全く理解できていません。しかし、少なくとも「比較的」良い理解が得られました。最近、30日間で自作のOSを作る本を見つけましたが、見た目は非常にシンプルで、細かい部分は省略されているものの、面白そうだと思っています。いつか時間ができたら挑戦してみたいです。シミュレーターを使うより、実機でテストする方が好きですから!

operating system-30

プログラミング言語

今年の初めに、松本行弘が書いた「まつもとゆきひろ 言語のしくみ」を偶然見つけました。その中で彼は最初から(yacc/lex)プログラミング言語を実装し、その原理や実装方法を一つ一つ説明しています。彼の完成度には驚かされました。単なる計算機の加減乗除だけではなく、文字列、時間処理、数字、ランダム、配列、アトミックなど、プログラミング言語に必要な基本的な機能が実装されています。

私も同様のことをしたいと思っていますが、yacc/lexのドキュメントが本当に理解できないため、C言語に対する理解がより深まった時に挑戦したいと思います。

もう一つは、IT鉄人戦に参加している際に、簡単なSvelte(リアクティブ機能なし)を最初から実装しようと試みたことです。簡単なパーサーを書いてみました。これはプログラミング言語に少し触れた感じですXD

今後も学ぶべきことがたくさんあります!皆さん、一緒にこの混乱の年を乗り越えていきましょう!

この記事が役に立ったと思ったら、下のリンクからコーヒーを奢ってくれると嬉しいです ☕ 私の普通の一日が輝かしいものになります ✨

Buy me a coffee