readfastの前半部

readfastの前半部の処理を追ってみます。
そもそも、この前半部の処理が、すんなり理解出来ずに、
きちんと自分の頭で考えないといけないなぁと思って、
readfastの読み解きをしようと思い立ったわけですけど、
コメントを読んだだけで分かった気になるのは、やはり、いかんですね。


それでは、処理順に見て行きましょう。

readfast:	; ALを使ってできるだけまとめて読み出す
;	ES:読み込み番地, CH:シリンダ, DH:ヘッド, CL:セクタ, BX:読み込みセクタ数

基本的には、BIOS サービスと、ほぼ同じパラメータですが、
BXのオフセット指定が、読み込みセクタ数の指定になっています。
つまり、オフセットは、指定出来ないという事になります。
まぁ、でも、セグメントって、16バイトの倍数で指定出来るので、
よっぽど中途半端なアドレスを指定しない限り、
セグメントの指定だけで十分だったりするわけですね。
ちなみに、CH レジスタが開始シリンダ指定で、CL レジスタが開始セクタ指定です。
CL が時々、シリンダの略に見えてしまいそうになるのは、僕だけかな?(^^;

	MOV	AX,ES		; < ESからALの最大値を計算 >
	SHL	AX,3		; AXを32で割って、その結果をAHに入れたことになる
	AND	AH,0x7f		; AHはAHを128で割った余り(512*128=64K)
	MOV	AL,128		; AL = 128 - AH; 一番近い64KB境界まで最大何セクタ入るか
	SUB	AL,AH

ここで、いきなり、僕は悩んでしまいました。
コメントを読めば、確かに、やりたい事は分かるわけですが、
これで、どうして、そうなるのか、納得出来なかったわけです。
まず、

	MOV	AX,ES		; < ESからALの最大値を計算 >
	SHL	AX,3		; AXを32で割って、その結果をAHに入れたことになる

ここでは、要するに、SHL ES, 3 って事になるわけだけど、
(あ、勿論、ES レジスタの値を変える意図はない)
通常、割り算は、右シフトなのに、何故、わざわざ、左シフトなのか、凄く疑問だった。
最終的に、AHと同じ内容を得ようと思えば、

	MOV	AX,ES		; < ESからALの最大値を計算 >
	SHR	AX,5		; AXを32で割って、その結果をALに入れたことになる

と書く事も出来るような気がする。
これであれば、右に1つシフトする毎に2で割られるわけだから、
5回シフトで32(2^5)で割る事になるわけだな... と、すんなり理解出来る。
まぁ、そもそも、何故、32で割るのか?って点についは、
ES がセグメントレジスタである事に理由があると思われる。
セグメントレジスタは、アドレス算出時に16倍されて利用されるわけなので、
レジスタに格納された値は、指定するアドレスを16で割った値だと考えられる。
既に16で割られた状態から、更に32で割るので、つまり、512で割る事になると。
結局、左に3ビットシフトしたAHの内容と、右に5ビットシフトしたALの内容は、同じであるから、
どちらでも良いと言えば、どちらでも良いように思うのだが、
何かの本に書いてあった、各命令の処理クロック数で、
シフト命令の場合は、シフトするビット数に比例して、クロック数が増えるような記述があったような気がする。
つまりは、より、クロック数が少ない手順を選んだという事になるのかな?


ひとまず、ここでは、指定アドレスを512で割っているという事になる。


で、続いて、

	AND	AH,0x7f		; AHはAHを128で割った余り(512*128=64K)
	MOV	AL,128		; AL = 128 - AH; 一番近い64KB境界まで最大何セクタ入るか
	SUB	AL,AH

ここでは、7bit目以上を強制的に0にして、0〜6bitを抜き出す事により、
128で割った余りを求めていると。
事前にアドレスを512で割っているわけだから、
AHの内容は、512のブロックが、いくつあるかという値になる。
そこで、512のブロックが128個で64Kになるわけだから、
128で割り切れない余りのブロック数が、64K境界からはみ出た分という事になる。
次いで、128から、はみ出た分を引くわけですが、
これが、指定した64K境界に読み込めるセクタ数という事になる?


本当ですかね???


ESで指定するアドレスが512の倍数である事って制限があるのかな?
でないと、中途半端なアドレスを指定した際、64K境界を越えちゃうような気がする。
具体的には、例えば、512*127+256みたいな、無茶苦茶意地悪なアドレスを指定したとする。
(+256)バイトの部分は、シフト演算の際に、捨てられちゃうので、得られる結果は、1となる気がする。
これで、512*127+256アドレスから、1セクタ分読み込んじゃうと、どうなるのかな???


う〜ん。


ひとまず、512の倍数であるって前提で考えよう。
それで、ここまでの処理で、ALレジスタに、64K境界までに読み込み可能なセクタ数が入ると。
そういう事で良いですかね。