トップ 差分 一覧 ソース 検索 ヘルプ RSS ログイン

「30日でできる!OS自作入門」読書メモ


30日じゃ終わらなそう。Kindle版で読んでると、ページを進んだり戻ったりが面倒なのでメモっておく。

 アセンブラ命令


naskという、NASMを筆者が拡張したものらしいのが使われている。

命令 説明
DB Data Byteの略。ファイルの内容を1バイトだけ直接書く DB 0x08
RESB Reserve Byteの略。指定されたバイト数をあけて0x00で埋める。 RESV 80
DW Data Wordの略。 DW 224
DD Data Double-wordの略。 DD 2880
ORG Originの略。メモリのどこの番地に読み込まれるかをアセンブラに教える。 ORG 0x7c00
MOV a, b aにbを代入。a,bにはメモリを指定することもできる。メモリ番地の指定に使えるレジスタはBX,BP,SI,DIだけ。 MOV AX, 0 ;(AX = 0;) / MOV AL, [SI]
JMP Jumpの略。指定されたメモリ番地に飛ぶ。 JMP 0x8000
ADD a, b aにbを足す。 ADD AX, 1 ; (AX += 1;)
CMP a, b aとbを比較する。 CMP AL, 0
JE jump if equalの略。もし等しければ指定されたアドレスにジャンプする。 JE 0x8200
INT ソフトウェア割り込み命令。 INT 0x13
HLT CPUを待機状態にする。 HLT
JNC jump if not carryの略。キャリーフラグが0ならジャンプする。 JNC 0x8200
JAE jump if above or equalの略。大きいかもしくは等しければジャンプする。 JAE 0x8200
JBE jump if below or equalの略。小さいかもしくは等しければジャンプする。 JBE 0x8200
JB jump if belowの略。小さければジャンプする。 JB 0x8200
RET
OUT 装置へ電気信号を送る。
IN 装置から電気信号を受け取る。


  x86 レジスタ


32ビットレジスタのリスト。ここを参考にした。

  • 汎用レジスタ ー EAX EBX ECX EDX
  • セグメントレジスタ ー CS DS ES FS GS SS
  • インデックス、ポインタ ー ESI EDI EBP EIP ESP
  • インジケータ ー EFLAGS

汎用レジスタ

各レジスタは16ビットレジスタ、8ビットレジスタに分解できる。
32ビット 16ビット 8ビット 名称 用途
EAX AX AH,AL アキュムレータ I/Oポートアクセス、数値演算、割り込み呼び出し、など
EBX BX BH,BL ベースレジスタ メモリアクセスのベースポインタ、割り込みの戻り値
ECX CX CH,CL カウンタレジスタ ループカウンタ、シフト演算(?)
EDX DX DH,DL データレジスタ I/Oポートアクセス、数値演算、割り込み呼び出し

セグメントレジスタ

セグメントレジスタは各セグメントのアドレスを保持する。
レジスタ名 名称 用途
CS コードセグメントレジスタ
DS データセグメントレジスタ
ES, FS, GS 拡張(extra)セグメントレジスタ ビデオメモリなどの far ポインタアドレッシング
SS スタックセグメントレジスタ DSと同じ値を保持することもある。

インデックスとポインタ

各々のレジスタはある特定の機能をもつが、いろいろな使い方がある(包丁は特定の機能(切る)をもつが、千切り、短冊切り厚切り、薄切りなどいろいろな使い方がある、と同じ意味だろうか?)。farアドレスを指定するためにセグメントレジスタと一緒に用いられることもある。"E"のプレフィクスをもつレジスタはプロテクトモードでのみ使用可能。
レジスタ名 名称 用途
ES:EDI EDI DI デスティネーション インデックス レジスタ 文字列および配列のコピーとセット、ESとともにfarポインタアドレス指定。
DS:ESI EDI SI ソース インデックス レジスタ 文字列、配列のコピーに使われる。
SS:EBP EBP BP スタック ベース ポインタ レジスタ スタックのベースアドレスを保持する。
SS:ESP ESP SP スタック ポインタ レジスタ スタックの先頭アドレスを保持する。
CS:EIP EIP IP インデックス ポインタ 次の命令のオフセットを保持する。読み取り専用。


EFLAGSレジスタ

(To be written.)

  メモ


p.40


BIOSの使い方を筆者が書いたページとして次のアドレスが示されているが、リンク切れして(ページが削除されて)いる。
http://community.osdev.info/?(AT)BIOS

似たような情報がこのページに載っている。英語。

p.42


以下のメモリマップのアドレスが書かれているがリンク切れ。
http://community.osdev.info/?(AT)memorymap

このページが情報としては同じだと思う。英語。

p.52


BIOSがつくられた時代はEBXレジスタ(32bit)はなかった。メモリ番地の指定には[ES:BX]というようにして、
ES x 16 + BX = (ES << 4 | BX)
でメモリ番地が計算される。ESに0xffff、BXに0xffffを入れたときのメモリ番地は
(2^16-1) x 2^4 + (2^16-1) = 1,114,095
となる。従って、この方法で1MBまでメモリ番地を指定できる。

どんなメモリ番地の指定でもセグメントレジスタを指定しなければならない。省略した場合、ほとんどの場合でDSを指定したものとみなされる。MOV CX,[1234]は、MOV CX,[DS:1234]の略ということ。

p.56


突然「トラック」という言葉がでてくるけど、これってシリンダと同じ?ここの説明をみると、トラックはある一枚のディスク上にある同心円状の記録領域で、シリンダは複数枚のディスクについて同一位置にある同心円をまとめて呼ぶときのものっぽい。同一シリンダに属するトラックはヘッドを動かさずにアクセスできるので、連続データは同一シリンダ状にくるように書き込むのが良さそう。

p.59


ディスクイメージが読み込まれるバッファのアドレスがES:BXで指定される。例のプログラム(harib00g/ipl10.nas)ではESが0x0820、BXが0に指定されている。ES x 16 + BX = 0x0820 x 16 + 0x0000 = 0x8200にシリンダ0、ヘッド0、セクタ2の内容が読み込まれている。ここから逆算すると、ブートセクタ(セクタ1、サイズ512バイト)の先頭は0x8000。

(いま気づいたけど、シリンダとヘッドのインデックスは0から始まるけど、セクタは1から始まるのね...)

haribote.sysはディスク上では0x4200に存在していて、ディスクイメージはメモリ上の0x8000から格納される(ただし例のプログラムではブートセクタはまだ読みこんでいない。セクタ2以降をメモリ番地0x8200から格納している。)のでメモリ番地0x8000 + 0x4200 = 0xc200にharibote.sysの中身があることになる。ブートローダから0xc200へジャンプしてharibote.sysが実行される。

p.60


INT 0x10, AH = 0x00 の解説がこのページには載ってないんだけど、どこかにあるだろうか。探してみたらここにあった。

p.63


INT 0x10, AH=00h, AL=0x13のときのVRAMは0xa0000からと書いてあるが、このページとかこのページの情報だと0xa000からのようにみえる。なんで違うんだろう。

p.65


オブジェクトファイルは他のオブジェクトファイルとくっつけるためののりしろに相当する情報をもっている。単独では機械語として一部未完成になっている。

p.67


WCOFF って何の略だろう?COFFがCommon Object File Formatの略らしい。Wはなんだろ?Wide?

p.68


bootpack.c の io_hlt() の宣言のところで extern が要らないのはなぜだろう。

このページによると、extern がデフォルトなので書かなくても暗黙のうちについていることになるから。

By default, the declaration and definition of a C function have “extern” prepended with them. It means even though we don’t use extern with the declaration/definition of C functions, it is present there.

p.69


ESP+4に一番目の引数(int)、ESP+8に二番目の引数(int)が入っているとして、ESP+0の指すアドレスには何が入っているんだろう?

p.70


C言語と連携するときに自由に使っていいレジスタは EAX, ECX, EDX の3つだけ。他は読んでもいいけど書いちゃダメ。

p.71


Pentium 4以降のCPUはここ

p.83


C言語でポインタpについて*(p+i)とp[i]は同じ意味。i[p]と書いてもアセンブラレベルでは同じコードが生成される。p[2]を2[p]と書いてもよく、実際これでコンパイルを通る。

p.88


またリンク先の中身がなくなっている...同様の内容と思われるページはこれ(英語)。

最終更新時間:2016年03月31日 15時11分50秒