おっとイカン、ちょっとひと休憩のつもりが、普通に寝てしまった。。 実は前回のエントリーは、アセンブラの命令を例として記述しまくっていたのだが、それがアメブロ上では「禁止タグ」扱いされてしまっていて、何度も修正を余儀なくされているうちにクタビレてしまったのだ。しかし、未だにどの部分が悪かったのかは不明。「取り合えず命令行っぽいものを全て抽象化したら上手く行った」というのが正直なところだ。うーん、勉強メモとしてここを選んだのは正解だったのだろうか。。

さて、本題に戻ろう。そうそう、実はキリの良い終わり方をしなかったんだっけ。NASKの新出命令はまだ続くのだ。

INT: 「interrupt」つまり割り込みを意味する命令。BIOS中に用意されている関数を呼び出すためのもの。

で、そうなるとBIOSって何なのさ?という説明が始まる。流石、予備知識ゼロからのテキストだ。ROM側に記憶されている、PC側で予め用意している基本的な入出力を扱うための関数群。と、ここでは捉えておけば良いのかな。どうやって調べたのか知らないが、ココ にBIOS研究の成果が公開されている。なるほど、文字列の表示はこういうメカニズムだったのかー、などとひとしきり感心。先人達の努力には感謝するばかりである。これが「学習の高速道路」というヤツなのだなー、と実感。

そして最後に、作者こだわりの一品(?)が登場。

HLT: 「halt」つまり停止を意味する命令。CPUを待機状態にする事で、省電力を心がけるべし、という事で常に意識しておきたい命令として紹介された。キーボードやマウス側で何らかのアクションがあるまで待機しているだけ、という事なので、「どうやって起こそうか?」については意識する必要はなさそうだ。(ここら辺もBIOSのおかげ?それともNASKが優秀なんかな?)

ふむふむ、命令群を説明してもらったおかげで、プログラムの中身が大体分かってきたぞ。

そして次に来るのがメモリマップの説明。簡単に解釈すると、「メモリはプログラムを作っている我々だけでなく、BIOSも使っていたりするので、何も考えないと競合が起きて大変な事になるよ。競合を意識的に避けるために、メモリのどこがどのように使われているか?、あるいは使うべきか?について地図のような形で整理したよ」という話かな。苦労の後が伺われる作者のメモリマップ研究成果発表場所はコチラ 。うーん、深い…

で、次でいきなり「ディスクイメージ全体をNASKで作るのは止めて、ブートセクタだけ作るよ。そっちの方が応用利くから」と宣言されるも、「応用って何だば?」という気持ちで一杯である。想像するに、ブートセクタはOS自身を読み込む為のプチプログラムに過ぎないので、いずれOS自身をブートセクタ以降に記述するようになる時が来るという事を踏まえると、ブートセクタだけで完結するように作っておくのが何かと都合が良い、とかそういう事なのだろう。深く考えるとハマりそうなので、いつもの通り「ふーん、そういうもんなのね」で、流しておくことにしよう。

しかし、いつもの通りサンプルを使って実際にディスクを作って試してみたところ、今までよりも格段に起動が早かったような、、、これは、1.44MB全ての領域にくまなくデータを書くのを止めたから、って事か?? マシン語への翻訳結果を出力してくれるツールの存在も嬉しい。何だかアセンブラがとても人間に優しい高級言語に見えてしまうから不思議だ 笑

そして「Makefile」あらわる

「Makeがいかに賢いか!」について熱く語られた。ものぐさな私的にも、キーボード入力の手間は出来る限り避けたいし、ディレクトリ内もキレイにしておきたいところなので気持ちは良く分かる。ただ、熱さは伝わったし、共感もしたのだが、特にここにメモするような発見があったわけでも疑問があったワケでもないので、「あらわる!」なんて言ったワリには特にコメント無し。

作者が立てたwikiなんかをのぞくと、結構上手く動作していない場合があるようなので、実際に試してみたが、これまた特に問題なく動いたので、そこについてもコメント無し 笑

うん。今日も乗り切ったぞ。


どうでも良いことだが、最近Google Mailを本格的に利用しだした。今まではYahooをメインに使っていたのだが、Google Mailのレスポンスの良さに思わず感激。乗り換えについて真剣に考えようかと思っている今日この頃である。Webアプリといえど、快適に使えるに越したことはない。職人魂天晴れである。そういう意味でも、今は良い勉強をしているのだろう。

さて、テキストの話に戻ろう。まずは先日の続きでアセンブラ(NASK)の新命令が登場。前回全てDB命令で記述されていた為、サッパリわけがワカラン状態だったプログラム本体を、もうちょっと可読性の高い形で表現しようという主旨らしい。

ORG: 「origin」の意を持つ命令。プログラムを読み込むPCメモリ上のアドレスを指定するのに使われる。なお、本命令中に「$」で示していた変数を用いた場合、それは前回までと異なり「現在位置」ではなく「プログラムが読み込まれる予定のメモリアドレス」を指し示す事になる。(プログラム開発者側で読込先アドレスを指定せずに、PC側が勝手に読込先をアサインするような事もあり得ると言うことか?後日述べられるかも知れないので、とりあえず理解し切れていないまま保留)

JMP: 指定されたラベルへとジャンプする。ラベルはC言語で言うところの関数名のようなもので、それが示す中身にはそれぞれ処理内容が記述されている。関数から別の関数へと処理が移っていくようなイメージで処理が進むようだ。なんだ、アセンブラ(NASK)って結構分かりやすいじゃないか。

MOV: 「move」の意を持つ命令。記法としては「MOV A,B」という形で用いられ、意味としては「A=B」となる。ただし、実際にはCopy命令であって、本命令によってデータコピー元にあったデータが無くなることはない。「B」はアドレスを意味するとは限らず、特定の値をプログラム上で指定できる場合もあることを踏まえ、こういう名前にしたのだろう、と勝手に納得。尚、実際は記法例で示した「A」の箇所にはレジスタを示す変数が指定される。つまり、この命令は「A」で指定したレジスタに「B」で指定した値を格納せよ、ということ。

ここで一旦、新命令の学習を中断し、新規に出てきた言葉「レジスタ」についての解説がスタート。

てか、そもそもレジスタって何だ?

一言で言えば、CPU自身に内蔵された記憶回路。代表選手は次の8つで、全て16ビットの記憶容量を持つもの。

AX:アキュムレータ(accumulator: 累積演算機)
CX:カウンタ(counter: 名前の通り)
DX:データ(data: 名前の通り)
BX:ベース(base: 「基点」の意味合い)
SP:スタックポインタ(stack pointer: スタック用ポインタ)
BP:ベースポインタ(base pointer: ベース用ポインタ)
SI:ソースインデックス(source index: 読み込みインデックス)
DI:ディスティネーションインデックス(destination index: 書き込みインデックス)

機能を意味するような名前がついているくらいなので、それぞれ何かの目的に特化して用意されているのだろうと想像されるが、とりあえず現時点では「色々なレジスタがあるんスね」くらいで流しちゃってくれという事のようだ。同じ命令でも、マシン語レベルに直すと長さが変わる(処理速度に響く。副次的には消費電流も?)等あるようなので、レジスタの使い分けについては、必要なときが来たらじっくり取り組もう。

覚えることが多いと忘れちゃうんだよなー、、と思いつつ読み進めると、実はまだ終わりではないようで・・・ 実は8ビットのレジスタもあるんだよ、という話が続く。

AL:アキュムレータLow
CL:カウンタLow
DL:データLow
BL:ベースLow
AH:アキュムレータHigh
CH:カウンタHigh
DH:データHigh
BH:ベースHigh

とはいっても、実はこれは前段で触れたレジスタを2分割(Lowが下位8ビット、Highが上位8ビット)したもので、記憶領域として別途確保されているものではないとの事。但し、SP、BP、SI、DIについては2分割できない。どうしても2分割するような処理がしたければ、一度MOV命令でAX等にコピーした後で対処すれば良いんじゃないの?というCPUの設計方針だそうな。昔のプログラムとの互換性問題か何かだろうか?追求したところで事態が変わるわけでもないので、ここらへんも「そういうもんなんだねー」くらいで流しちゃって良いところなのだろう。

で、実はまだ続く。そう。32ビットの話がまだではないか。まだ覚える事あんのかー、と気持ちが萎えそうになりながら読み進めると、なんだ簡単。16ビットのレジスタの頭にそれぞれExtendを示す「E」をつけてあげればOKで、しかもそれぞれの下位16ビットがそのまま前段の16ビットレジスタそのものなのか。8ビット→16ビットの時と異なり素直に進化してくれて嬉しい限り(笑)上位16ビットの側には名前がなく、ちょっと使いにくいような気もするが、本当に困るかどうかは、本格的にプログラミングするようになってから考えよう。

最後にオマケ的に、セグメントレジスタなるものについての情報が出るも、「そんなのもありますよ」程度で今は流してOKのようなので、「ふーん、何かまだ居るのね」くらいに思っておくことにする。この本は、初見で全てを理解しようとすると破綻するっぽいし。。

そしてアセンブラ(NASK)の説明は続く。まずは簡単に要約すればラベルの扱いについてだ。ラベルはC言語でいうところの関数名ではあっても関数そのものじゃないよ、というのが主旨と理解すればよいのだろう。つまり、「プログラムが格納されたアドレス」を格納する命令であって、「アドレスが指し示すプログラム自身を取り込め」という命令ではない、という話。

そして次はメモリの話。これまではCPU自身が備えているレジスタに情報を格納する、という話だったが、32ビットのレジスタを全て足しても32バイトにしかならない現実を踏まえると、ブートセクタに格納されている僅か512バイトのデータすら読み込めないので、CPUの外にあるメモリを有効に使わないとね、という話。さらに言うと、「でもCPUの外にあるメモリを使う場合、レジスタのみを利用した場合と比較すると、どうしても処理が遅くなるよ」という点も挙げられている。メモリアクセスを可能な限り減らす事が、高速化に向けたポイントになるという事が言いたいのだろう。

で、アセンブラ(NASK)に話が戻る。 NASKではメモリ上のアドレスを指定したい場合「[」記号を使って区別する(命令名、データサイズ、[書き込み先アドレス]、書き込む中身の順で宣言)。データサイズの部分をWORDやDWORDと変えてやる事で、確保する領域サイズを決定できる。但し、メモリに格納するデータは、下位バイトから順に格納されていく(いわゆる、リトルエンディアン)点に注意。また、書き込み先アドレスの指定方法として、レジスタを使う事も可能。この場合、レジスタに格納されている値のアドレスが指定されたものとして処理される。ちなみに、CPU設計上に絡む制限で、これが許されているレジスタは一部(BX,BP,SI,DI)だけである点は注意。SPのニ分割問題等と一緒で、どうしてもこれ以外のレジスタ(AXなど)を使いたい場合は 、適切なレジスタにコピー(MOV)してからやりましょう、との事。まだちょっと「だからなんなのか?」のイメージが沸かないが、ここも「そういうものなのねー」という感じでまずは流しておく事にする。

そして引き続いてはADD命令。見ての通り足し算をさせるもの。記法は「ADD 対象物,利用する値」の構成。 となる。カウンタを1ずつ増やして特定回数同じ処理を続ける、みたいなロジックは結構多いのでお世話になりそうだ、と思っていたら次に出てきたのがCMP命令。「compare」の意味するとおり、比較のための命令となる。まさにそれだよ、というヤツである。実際には、比較した後でその結果を踏まえて行うべき処理とセットで使う事になるわけだが。

はー、随分長くなってしまったので見易さを考え一旦終了。後半に続く。


2日目はエディタの紹介から始まった。作者おススメはTeraPad というツールらしい。ちなみに本来私はPeggyPad 派である。ファイルを生成する段階で指定したプログラミング言語の予約語を、色を変えて表示してくれる等の機能が嬉しく、重宝していた。特に、最近アプリのWeb化が進む中、仕事でJavaScriptを使ったプログラムを書く事が増えた関係で、JavaScriptをサポートしているという点は重要だ。しかし、たまーに巨大なオープンソースのコードをチェックしようとすると、ファイルサイズ上限問題が出ていたのが不安のタネだった。(そういう人には有料版を、という方針らしい)

しかし、NASKってどうせ作者オリジナルのアセンブラなワケで、考えてみるとどんなエディタを使ったところで、予約語の表示変えのような事は行われるハズもなし、という事で、今回は物色の意味も兼ねて新しく紹介されたこのTeraPadなるツールを使ってみる事にしようと思う。はてさて。。