/var/log/hdk.log

2019 年 12 月中旬


10 (火)

%1 8088

8086 Architecture

この図を見て悩まされている。ALU とつながる内部のバスが 16 ビット。 このバスは共用なのだろうか? つまり、複数の 16 ビットレジスターの内容を同時に ALU に食わせることはできないのだろうか? Temp.Registers の存在もあって、できないというのもあり得るとは思う。

問題はシフト命令のクロック数で、1 ビットのシフト命令は、なんと 2 クロックで済むということになっている。 シフト命令もフラグの反映があるので ALU での処理と見て間違いないだろう。 また、1 ビットシフトなので 1 入力 1 出力で、インクリメントなどの命令が 2 クロックというのに近い。 しかし、2 クロックの INC 命令が 1 バイトなのに対し、シフト命令は 2 バイトである。 そして 2 バイト目を見ないとどのレジスターに対する操作かがわからない。 レジスター同士の足し算などの命令は 3 クロックだが、全加算器がキャリーを処理していくのに時間がかかるからかとも考えた。 しかしそれでは論理演算命令も 3 クロックなのが説明できない。1 クロックの間に 2 バイト分の命令の処理ができるのか? 3 クロックかかる 2 バイト命令は 2 オペランドだからか? それも 2 バイト分の命令のデコードは 1 クロックで済んで、レジスターを 1 個ずつ内部バスで転送しているから 3 クロックなのか? ウーン... 2 バイト 2 クロックの MOV CS 命令の時に半分の時点で %cs が変わっているっぽかったのも気になるし...

2019/12/10 のコメントを読む・書く


11 (水)

%1 すいようび

12 月中旬にしてはやや暖かい日。 職場近くの銀杏の色づき具合が、先週頃は日当たりの差でバラバラになっていておもしろかったけど、だいぶマシになっていた。 とはいえ、まだほとんど散っていないあたり、去年以上に変な感じ。

夜帰る頃に、職場近くの駐車場に駐まっていた車が濡れているのに気づいて、あれ、雨降ったんだな、みたいな感じで、まったく雨に降られることなく帰宅できた。

%2 Portfolio

Grp3 の 1, TEST 命令の隣が TEST 命令かどうかを調べた。

 9c50f6c8019c50f6c8049c50 11311311 01B4 F102 01B4 F146 01B4 F102
 9cf6c0019cf6c0049c 13131 F102 F146 F102

値も変わっていないしフラグは同じで TEST っぽい。

しかし... ここでまた発見があった。 フラグレジスターのビット 12〜15 が必ず 1 だというのは、Intel のマニュアルにも書かれている話で、まったく問題ない。 問題はビット 1 で、80x86/80x87 ファミリー・テクニカルハンドブックという本には、8086 のフラグレジスターはビット 1 が 0 だよ、と書かれていたはずなのだが、今ここで見えているのは、Intel 80C88 のフラグレジスターはビット 1 が 1 ということだ。 はぁ。

じゃ、JX に積まれていた 8088 はどうだったか? というと、メモリーダンプを保存した時のデータが手元にあって、ディスケットに書き込むプログラムごとまるまる残っていたのでスタック領域もそこに含まれていた。 その中でそれっぽい値を見つけると、0xf246 というのがあった。Disk BIOS を呼び出した時のものだろうか、割り込み許可でゼロフラグが立っている、ありがちなやつだ。 さらに、BIOS の中で発生した割り込みらしき、0xf800 の手前に 0xf093 というのも残っている。 ビット 1 は立っていることになる。 意外と本もあてにならないよな...

2019/12/11 のコメントを読む・書く


12 (木)

%1 東京大学

仕事で某 Summit のため昼頃から東京大学へ。 学食に行ってみると昼間の時間帯は学生教職員優先で部外者は遠慮しろとある。 なかなか面倒な大学だ。 筑波大学ではそんなのなかったのに。 それで学外のカレー屋さんに入ってみるとなかなかよかった。

帰りはなんか途中駅で非常停止ボタンが扱われたとのことで駅間で非常停止があった以外は普通だった。 なんか、非常停止、体感でわかるな。 立っている人の一部がバランスを崩すほどの減速感、やや常用ブレーキより強く感じられる。 怪しいなと思っていると、緊急停止しますの自動音声アナウンス。 そこまで来てもボケッとしている人達は構えができておらず、停車寸前にばたばたとバランスを崩していく。 おいおい。 非常制動入ってたら運転士でもゆるめられないもんな。

%2 Portfolio

まだまだ undocumented instructions を試す。

fed050 00000000000000000000...

CALL AL? にあたる機械語、まさかの無限ループw こりゃなかなか難しいかな? まぁもうちょっと試そう。

31c0fed0 2A 0002 0366 F146 F1B8
31c0ffd0 2A 0002 0366 F146 01B8
31c0fee0 2A 0002 0366 F146
31c0ffe0 2A 0002 0366 F146

%ax をゼロクリアしてからの CALL AL, CALL AX, JMP AL, JMP AX 相当、なんか CALL AX と同じような挙動をしているように見える。 が... よく見るとスタックに差異があるな。 しかし 0 番地に cd 20 入ってないのかな? いやこれ割り込みのスタックか? 割り込みって TF クリアされるんじゃなかったっけ? まぁいいか。

31fffed7 2B F1B8
31ffffd7 2B 0002 0366 F146 01B8

%di で試そうとしたやつ。 よく考えたら %bl になっているような気がする。 全然違う結果になったなと思っていたがそのせいか。 しかし 01B8 のところが戻り番地のはずで、それが F1B8 と push されている。

50fef050 121 01B4 F1B4 01B4
50fef850 121 01B4 F1B4 01B4
31c0fef0 22 F100
31c048fef0 212 F1FF

PUSH AL にあたる機械語、1 バイト分だけスタックに積まれているように見えるw 上位 8 ビットが 0xf1 って何だろうと思っていたが、もしかしてこれ、TF 立てているから必ずスタックにフラグが残っていて、その上位 8 ビットが見えているだけかも。 もうちょっと試したいが、ま、いいや。 気分を変えて LEA AX,AX を試そう。

8dc050 21 FFF8
8dc150 21 FFF8
8dc851 21 FFF8
508dc050 121 FFF6 01B4
a100008dc050 321 FFF8

ふん、なんかどれもスタックポインターっぽいな。 もしかしてこれも TF のせいか? 試しに MOV SS を使ってみる。

8c1600018e1600018dc050 461 0100

ほぅ、0x100 が出てきた。 前の EA (Effective Address) がそのまま出てくるっぽい感じが... まぁありそうな話だが、そうなると TF クリアして試したほうがよさそう。

9c519da100008dc09d50 1118 0000 0000
9c519d90a100008dc09d9050 1119 0000
9c519d9001c88dc09d9050 1118 FFF6
9c519d90f6e48dc09d9050 1118 FFF6
9c519d90ac8dc09d9050 1117 0001
9c519d90ad8dc09d9050 1117 0002
9c519d90e2008dc09d9050 1117 FFF6

TF を消して試したいろいろ。 ちょっと POPF で面倒な感じになったので NOP を入れた。mov 0,%ax 後に LEA AX,AX すれば 0 が出てくる。 つまりクロック数計算に +EA が出てこない命令でも、メモリーアクセスで使ったっぽいアドレスが残っている。 レジスター同士の ADD 命令や MUL 命令では、変化しないらしくスタックのアドレスが残っている。 そして LODSB を試したら 1, LODSW を試したら 2 が出てくる。LOOP も試してみたらこれは変化はない。 何なのかというと、LODSB がアクセスしたのは 0 番地なのに、1 が出てくるってことは、LODSB の後の %si の更新で EA として残っているアドレスが変化するということ。 よくわかんないけど +EA のシステムと同じ計算機能を使っているのだろう。 それで LOOP も (フラグが変化しないので) EA を使うのかと一瞬思ったが、関係はないわけだ。

あとスタックポインターも POP の後、足した後の値が残っているのはおもしろいところ。8086/8088 が PUSH SP の際に 2 引いてから SP を書き込んで、POP SP の際は 2 足してから SP に書き込むので POP 前に戻ってしまうのは有名な話。 しかし 2 足した後の値が残るということは、POP 命令が BIU に SP のアドレスで読み取り要求を出してから、その結果をもらってレジスターに書き込む前までの間に、2 を足してレジスターに書き戻しているということか。

というわけでまたしても新発見をしてしまった。 残っている EA が読み取れるというのは、なんだかレジスターがひとつ増えたみたいで楽しい。

なお、全然別の Atari Portfolio の操作上の癖も発見した。Fn+O で電源をオフにするときは、Fn よりも O を先に離さないといけない。Fn を先に離すとその時点でオフになり、O を離した時にまた電源がオンになってしまう。

2019/12/12 のコメントを読む・書く


13 (金)

%1 きんようび

寒い日。

飯田橋と水道橋を勘違いして列車を降り、改札まで行ってから様子がおかしいなと思って調べて、また列車に乗り直すというあるある事例。 中央線の各駅停車 (中央総武線) の駅だということはわかるが、水道橋、飯田橋、市ヶ谷、あたりの位置関係はどうもあやふやな感じ。

%2 Portfolio

9c519d905159fef0589d9050 1119 00B4

フーン。 上位 8 ビットは前の値が残っている様子だから、やはりこれは、下位 8 ビットしか書き込まない PUSH 命令か。fef0 で push %al (?) ということ。

9c519d90fef4589d9050 1117 F001

ちゃんと push %ah (?) もできる。 例によって fefc にしても同じ挙動であった。JMP 命令や CALL 命令は挙動を調べるのが大変... せっかく TF で試すプログラム作ったんだからへんなところに飛んだ時の CS:IP を出すべきだった。 いや、それくらいなら簡単に試せそうだな。

2019/12/13 のコメントを読む・書く


14 (土)

%1 スクーター

スクーター (アドレス) の後輪ブレーキの戻りが悪い件の対策、先日に続いて再挑戦。 前カウルをすいすいと外し、メーターまわりをおそるおそる外したら何とかできた。 外してみてわかったが、ヘッドライトの向き調整用のねじは外さなくていいみたいだ。 方向指示器やヘッドライトはくっついたままでいい。

さて、カウルの裏にはママチャリみたいな金属製のハンドルが存在する。 スクーターのハンドルってこうなっていたのか。 確かに強度を考えると中まで全部プラスチックというわけにはいかないのだろう。 で、左側のブレーキレバーのところは、自転車なんかと同じようなものだ。 カバーを外し、ねじをゆるめ、ゆる、...、ゆるまない。 ウーン。 このねじをなめるわけにはいかないぞ...

それで、反対側のナットをゆるめようとしたら、方向指示器のスイッチの本体の部分が邪魔をしてソケットレンチが入らなさそう。 それで方向指示器のスイッチのねじをゆるめたが、あんまり動かせない。 ちゃんとスイッチを外さないといけないのか? とぐりぐりやっていた時、カウルがプラスチックなものだから、少し変形してソケットレンチが入りそうなことがわかった。 なるほどこうやるのか。 そんなわけで六角ナットは簡単にゆるみ、レバーを外すことができた。

そして、ブレーキワイヤーを、これどうやって外すんだっけな、と調べて、ずらしてワイヤーのところを合わせれば外れるのか、と理解して、何とか外せた。 引っ張られて作業しづらい時は、後輪タイヤ脇のブレーキを直接押し込めば多少マシになる。 で、ワイヤーに注油するのだが、手頃なオイルがないなと思って、とりあえずチェーンソーオイルを突っ込んでみたら、全然入っていかない。 ウーン。 何度も動かしながらちょっとずつ入れていったが、後輪タイヤ脇のブレーキを押し込みながらやるのはなかなか難しい作業である。 今思えばタイヤ脇のねじをゆるめてしまったほうが早かったな。

そんなこんなであんまり注油できた気がしないまま、手で動かしているとなんか多少軽くなっている気がした。 それでとりあえずワイヤーをはめ込み、レバーを元の位置に戻して、握ってみると、なるほど良好である。 ブレーキレバーに近い側がひどかったんだな。

それじゃ試運転だ、というわけで、ねじとカウル類を全部元に戻し (線を挟みそうになって焦った)、レバー位置の調整をしつつ出発。 良い。 かなり良い。 チェーンソーオイルを使ったのはちょっとアレだが、まぁいいか。 ジョルカブやジョルノなどと違って、アドレスの場合、ブレーキレバーのまわりまでカウルがガッツリある分、作業性はとことん悪いけれども、汚れの入りにくさという点では結構良いはずだし。 カウルだけでなく、ちゃんとブレーキレバーのねじの部分のゴムカバーまである。

%2 Portfolio

こないだのテストプログラムで lea 8(%bp), %sp のところの 8 を 2 に変えれば、フラグレジスターと CS:IP も見えるようになるので、バイナリーで書き換えて準備した。

JMP の前にまず PUSH 命令の確認。 バイト幅 PUSH にメモリーアドレスを指定してみた。0 番地には cd 20 が入っているのでそれを利用する。

fe360000 4 01B8 0366 F102 F1CD

メモリーアドレスの場合もやはり、SP は 2 引かれて、そこに 1 バイトだけ書き込まれる形のようだ。 それでは CALL 命令の確認。

fe160000 9 FFCD 0366 F102 F1B8

おっ? IP の下位 8 ビットしか書き込まれないのは PUSH 命令と同じだが、その後 IP が 0xffcd になっている。0xff はどこから出てきたのか? CALL FAR も試そう。

ff1e0000  20CD 16FE F102 01B8 0366
fe1e0000  FFCD FFFE F102 03B8 F166

上が通常の CALL FAR [0] で下がバイト幅の CALL FAR。 このコードに入ってくる直前の IRET 命令で使ったフラグレジスターの 0xf1xx と CS の 0x0366 が残っているはずと考えれば、CS:IP の書き込みもやはり下位 8 ビットしか書き込まれないようである。 そしてジャンプ先の上位 8 ビットが 0xff なのも同じで、セグメントもオフセットもそうなっているが、上と比較すると、ちゃんとセグメントがオフセット 2 から読み取られたらしいことがわかる。 読み取り長は 1 バイトにされてしまっているが、それ以外の SP の計算やダブルワードの読み取りでの 2 という数字はそのままなんだな。 さて 0xff とは...

81ec0001fe1e0000 4 FFCD FFFE F182 03BC F166 F206 F206 ...
8c1600018e160001fe1e0000 4 FFCD FFFE F102 03C0 F166

%sp を 0x100 引いてやることで、0xfe になるのでは、という期待を持っていたが、ならなかった。 また、0x100 番地を使って %ss に書き込んだ直後にすると 0x01 になるかも、という期待もあったが、ならなかった。 特に理由無く、単に 0xff になるのか。

さて、CALL FAR はすぐに止まってくれて実験しやすいので、もっとひねくれたことをしよう。CALL FAR AX はどうなる?

ffd8  0164 E000 F102 01B6 0366
fed8  0164 FF00 F102 03B6 F166
31c0ffd8 2 0164 E000 F146 01B8 0366
31c0fed8 2 0164 FF00 F146 03B8 F166
acffd8 1 0164 E000 F102 01B7 0366
acfed8 1 0164 FF00 F102 03B7 F166
ff36f8ff 4 01B8 0366 F102 24D7
ff36faff 4 01B8 0366 F102 E000
8c1600018e160001ffd8 4 0366 E801 F102 01BE 0366
8c1600018e160001fed8 4 0366 FF01 F102 03BE F166
1617ffd8 1 0164 E000 F102 01B8 0366
511617ffd8 11 0164 24D7 F102 01B9 0366 0004

どこから出てきた 0xe000, と思ったら見事にスタックポインター由来、いや、これは EA 由来だ。mov 0x100, %ss を入れたテストで 0xe801 の 0x01 はテストプログラムの最初の mov の最後のバイトで、0xe8 は次の call の最初のバイトなので、EA を見ていると言ってよさそう。 しかし最初の 0x0164 の由来がわからない。0xfff8 に書き込まれているのは 0x24d7 らしいし、%ax に入っているのは開始番地の 0x01b4 である。 いや、31c0 は xor %ax, %ax でつまり %ax を 0 にしても結果は変わらない。ffd9 など、違うレジスターを試しても結果は変わらなかった。

テストプログラムのバイナリーを見直すと、そうか、コード開始前とトラップのリターン前に書き込んでいる to のアドレスが 0x164 だ。 しかし EA はその後の pop と iret で変化しているはずだし、それだと mov 0x100, %ss の後だと 0x100 にならないとおかしいような? とにかく何らかのチャネルに残された値がそのまま出てきているということか? なんもわからん。

いや、ひょっとして、LES 命令でも同じことを試せる?

c4d85306 211 01B8 0366 F102 E000 F102
9c519dc4d88dc09d90530650 111711 01C0 0366 F102 FFF8 24D7 F006

んー? 違うのか... わからん...

ところで、関係ないけど LES 命令の後って割り込み禁止になるのかどうか。

c43f90 21 01B7 0366 F102

ならないみたいだ。

2019/12/14 のコメントを読む・書く


15 (日)

%1 クリスマスパーティー

某研究室のクリスマスパーティーに顔を出してみた。

バイクで、行きは首都高・常磐道経由。 首都高の中央環状線の一部が工事で通行止め、さらには 6 号が中央環状線と交わるあたりから渋滞、また 6 号に分岐するところが工事中で車線規制だった。 まぁバイクだったのでするっと割り込み...

帰りは一般道で。 寒い! 橋のところで気温 5 度と出ていて、そりゃー寒いわな。GOLDWIN のインナーグローブというのを買ってみたので試してみたんだけど、ごわごわして操作しづらい割には指先は冷えるという結果に... 環八通りまで来てやっとマシな気温になった。

%2 Portfolio

LES 命令にメモリーオペランドを指定しなかった場合の挙動、どうも最後にアクセスしたメモリーの内容が出てくるっぽいんだな、これ。

9c519d3904c4d88dc09d90530650 111911 01C2 0366 F102 0002 16FE 20CD
9c519d3804c4d88dc09d90530650 111911 01C2 0366 F102 0002 16FE FFCD
9c519d803e000101c4d88dc09d90530650 111C11 01C5 0366 F102 0102 E801 FFBF
9c519d833e000101c4d88dc09d90530650 111C11 01C5 0366 F102 0102 E801 B4BF
9c519d823e000101c4d88dc09d90530650 111C11 01C5 0366 F102 0102 E801 FFBF
9c519d803e010001c4d88dc09d90530650 111C11 01C5 0366 F102 0003 0016 FF20
9c519dc6060001dec4d88dc09d90530650 111C11 01C5 0366 F102 0102 E801 FFDE
9c519dc606000178c4d88dc09d90530650 111C11 01C5 0366 F102 0102 E801 0078
9c519d880e0001c4d88dc09d90530650 111B11 01C4 0366 F102 0103 E801 0004
9c519d50c4d88dc0599d90530650 111911 01C2 0366 F102 FFF6 F102 01B4

で、バイトアクセス時の上位 8 ビットが 0xff なのはやはり内部の挙動なんだな。 と思ったんだけど 0x78 のところ符号拡張だな... つまり、読み取り時は符号拡張ではなく 0xff が入るっぽいが、書き込み時は符号拡張になるのか。 即値で符号拡張を使うケースが (上の cmpw もそうだけど) あるので、使うにしろ使わないにしろ、符号拡張がされているというのは変ではない。 ま、それはいいとして、EA の他にデータが残る場所があるってことだ。BIU 側の内部レジスターなのかな。

2019/12/15 のコメントを読む・書く


16 (月)

%1 休暇

久しぶりに天気のいい平日休暇。

整形外科。 こりはともかく、痛みがなければ来なくて大丈夫、痛みが出る時は集中的にリハビリに来たほうがいい、的な。 ふむ。 最近は横向いて寝られるのでだいぶ調子はいいほうなんだよな。

武蔵境通り、なんか工事していたのは終わって片側 2 車線の区間がかなり伸びたんだな。 何も知らずに軽い気持ちで原付で通って、予定外の二段階右折をする羽目になった... ここを通るバスの時間もだいぶ安定するようになったんじゃないかな。

レンタルカート。 飯能。3 回乗ってベストタイムは 33.96 秒くらい。 何度か 7 コーナーでジャンプしてしまった... インリフトを意識してみたら、7 コーナーもできてはいるが、そこからアクセルをポンと踏んで、外側しか接地していない後輪がそれでグリップの限界を超えて滑って横向きの力が生まれ、その結果内側の後輪も接地するというだめパターン。 慎重な操作が必要だ。 スタッフさんよれば 4 コーナーと 9 コーナーは意識的にリフトさせるそうだ。 なお 4 コーナーは確かに浮くんだけど、それは高速からの減速があるからで、浮かせるのたのしーとやっているとクリッピングポイントを外してしまう気がする。 たぶん、後輪しかブレーキがないのに、その片方が浮いてしまうことで減速の力が足りていないような、つまりもっとまっすぐの状態でちゃんと減速したほうがよさそうな感じかなぁ。 まぁともかく、自分はもっとステアリングの操作を精密にするべきだとは思った。 もちろん 10 年前の自分と比べれば遙かにいいけど、意識しながら走ってみるといろんなところで雑に回していることがあるのに気づくので、それがタイムが安定しない要因のひとつなんだろう。

飯能へは車で、東青梅ルートを使ったんだけど、帰り、ボケッと走っていたら橋を渡るのをすっかり忘れて都バスが走るルートを行ってしまった。 頭の中で道順が整理されておらず、交差点の順番が混乱していたせいでもある。 そうしたら成木五丁目の交差点にパトカーが何台か駐まっていて、何かあったっぽい雰囲気。 なんだろうな。 道を間違えていたのに気づいたのはその後の交差点だった。 別に方向は間違えていなかったけど、なんでこっちの道に来たんだっけとそのときは首をかしげていた。

2019/12/16 のコメントを読む・書く


17 (火)

%1 かようび

朝は雨。 しかも寒い。

テレビドラマ『新米姉妹のふたりごはん』、フォアグラでてきちゃったし、「ちょっとフランスに行ってくる」ってせりふもなかなかw しかし美味そうに食べるなぁ。

テレビドラマ『釣りバカ日誌』の再放送をやっているっぽいだけでなく、TVer に過去作の『弁護士のくず』と『結婚できない男』が出ているのを見つけてしまった。 全話はないのかも (よく見ていない) だけど『弁護士のくず』は原作もドラマも全部見たし懐かしいな。

%2 Portfolio

そういえば TF をセットするのに POPF の後に NOP を入れておかないと変な挙動をするなぁ、というのがあったので少し試した。

9c519d9d9090909090 1113111 01BD 0366 F102
9c519d9d87c0909090 111411 01BD 0366 F102
9c519d9d2687c09090 111411 01BD 0366 F102
9c519d9d262687c090 11151 01BD 0366 F102
9c519d9d26262687c0 1116 01BD 0366 F102
9c519d9da900009090 11151 01BD 0366 F146
9c519d9db800009090 11151 01BD 0366 F102
9c519d9df7c0000090 1116 01BD 0366 F146
9c519d9df74600000090 1117 01BE 0366 F146
9c519d9deb009090 11141 01BC 0366 F146
e2fe 0002 01B6 0366 F146
9c519d9de2fe 111102 01BA 0366 F146

ははーん。TF をセットする POPF 命令の、すぐ次の命令の実行後に割り込みが発生するのが今時の x86 だが、当時は次の次の命令の実行後になっているっぽいな。 ただし、プリフィックスを 1 命令として数えて、だ。 なのでプリフィックスをたくさん付けて命令長を無駄に伸ばせば、今時の x86 と同様に次の命令で発生する。 最初はプリフェッチキューが関係あるかと思ったが、eb00 でわかるように、プリフェッチキューは関係ないようだ。

f4f4f4f4 1111 01B8 0366 F102
fb9c519d9df4 1111 1545 E000 F002 01BA 0366 F302
9c519dfbf4f4f4f49d9090 1118 01BF 0366 F102

これはおまけの HLT の実験。 試行錯誤の結果うまく取れる方法が見つかった。 なんと TF をセットしたまま HLT しても、止まってくれないw POPF の次の命令直後に割り込みが発生しないのを逆手に取り、POPF の次に HLT を入れると、いい具合に HLT に入るってことかな。TF をクリアしておいて HLT に入るのは OK, 何個か並べておいたら、キーを 2 回ほど押すまで先に進まなかった... つまりタイマー割り込みは毎秒 1 回も発生していないようだ。 カーソルの点滅もハードウェア側だな。

なお、Linux KVM 上で試したら fb (sti) 入れただけで hardware error 0x80000021 が出たww そんなバカなw

How does single-stepping on the 8086 interact with internal and external interrupts? - Retrocomputing Stack Exchange

TF の話はこちらにも載っている。8088-1 だが説明を良く読むと次の次の命令というのは同じ挙動のようだ。 ここでは外部割り込みも絡んでおもしろい話になっている。 通常であれば INT 1 の中が割り込み禁止で、IRET で割り込み許可になっても、その直後の命令で外部割り込みは発生しないはず。 たぶん。 しかし INT 1 の中で IRET の直前に割り込み許可にしたら、うまく割り込みが発生させられるかも知れない。

c6066601b8fbe2fee2fe  1545 E000 F002 01BC 0366 F302

と思いつつこんな実験をした。 バイト数を表示するルーチンをつぶした上で、割り込み許可して何もしない LOOP。 止まっている間にキーを押す。 すると、割り込みは発生してしまった。 それも... LOOP 命令に戻る割り込み PUSH 後に続けてキーボード割り込みハンドラーらしきアドレスの PUSH である。 なんだこりゃ、と思ったが、これって動作としてはさっきの Stack Exchange の書き込みと一致しているわけか。 フーン。IRET 命令の直後に割り込みは発生しないのかと思ったが、そうでもないってことかな。

c6066601b8e2fee2fefb909090  1545 E000 F002 01BE 0366 F302

さらなる変形パターン。LOOP 後に割り込み許可、LOOP 中にキーを押す。 これも STI 直後に割り込み発生という結果。 しかしこれは? TF 絡みだからでは?

fb9c519de2fee2fe9d909090 1111 1545 E000 F002 01BE 0366 F302
9c519de2fee2fe9dfb909090 111 1545 E000 F002 01BE 0366 F302

ウーン、それっぽいかな。 ま、いいや。 この知識を使えば CALL FAR AX の件の詳細を追えると思う。

2019/12/17 のコメントを読む・書く


18 (水)

%1 すいようび

暖かい日... どうなっているんだ、この気温は...

%2 Portfolio

まだまだ試すぞー!

9c519de2fee2fe9dfbfa9090 111711 01C0 0366 F102
9c519c519d9d9d9d909090 111113111 01BF 0366 F102
9c519c519d9d909d9d9090 1111133 01BF 0366 F102
9c519c519d9d909d 111113 01BC 0366 F006 F102
9c519c519d9d9d909d9090 1111133 01BF 0366 F102
9c519c519d9d9d90 111113 01BC 0366 F006 F102
16161617171790 1114 01BB 0366 F102
16f317ac51 131 01B9 0366 F102 0004
1617f3ac51 1100021 01B9 0366 F102 0000
9c16519c519d9d9d179d9090 1111116 01C0 0366 F102
9c51169c519d9d179d9d9090 11111133 01C0 0366 F102

CLI の状態で外部割り込みが発生するのか実験、さすがに発生しなかった。 それから TF のクリアとセットを繰り返す実験、なんとクリアした状態でも発生した。 ほう。 それで検討のため少し POP SS を試す。 念のためと思って POP SS を連続して並べて実行してみたら、なんと全部の POP SS の間でシングルステップ割り込みは発生しなかった。 これは予想外! だから、PUSH SS までブロックがされちゃうバグ入り 8086 でも、動作に支障はないんだな。

ま、それはいいとして、それで POP SS が実は prefix 的な挙動なのではないかと疑って、prefix と混ぜて使ってみた。 が、さすがに prefix とは別扱いだ。 割り込みが発生しないだけ。POP SS 直後に REP も試したけど、最初の 1 周分の後はちゃんとシングルステップが働いている。

それで... だ、POPF で TF=1 に戻した時、その次の次の命令の実行後にシングルステップ割り込みが発生するというわけだった。 なので、TF=1 にした命令の次で TF=0 にして、その次に POP SS を入れたらどうなるか? というと、TF=1 は無かったことになった。 ここまで見て思ったのだが、TF=1 にした命令の次の次の命令というより、TF=1 にした命令の次の命令の実行前に TF はちゃんとチェックされていて、しかしその命令がもうひとつ次の命令まで割り込み禁止のように扱われて (STI 後の割り込み禁止的な)、それで遅れているように見える感じがする。 なので POP SS を入れればまた 1 命令割り込み禁止が働いて、シングルステップ割り込みも禁止対象となり忘れ去られたのでは。 でもこれきのうの実験でそのタイミングで外部割り込みが発生しているから、完全な割り込み禁止ほど強力ではなさそう。

あときのうの TF=1 でも外部割り込みが発生するやつ、ひょっとして受け付けた外部割り込みが 1 命令分の扱いになっている? 機械語があるわけじゃないので 0 バイト命令だけど。 それならきのうの fb9c519de2fee2fe9d909090 実験で 9d90 の次で割り込みが発生したのも納得だし、そのときに割り込みハンドラーの入口でシングルステップ扱いになるのも納得できる。 以下の通りキーボードは割り込み 9 でベクターは E000:1545 になっている。

31c08ed8ff362400ff362600 264 01C0 0366 F146 E000 1545

2019/12/18 のコメントを読む・書く


19 (木)

%1 もくようび

ついに職場で流行性感冒感染者が発生。 社長!

TVer で久しぶりにテレビドラマの『弁護士のくず』を見た。 懐かしい。 ドラマを見ていると原作漫画を思い出した。 今は同じ作者が刑事ものを連載しているが、くずの主人公の顔は今思い出しても特徴的だったな。 なお今の刑事ものもある意味くずである。

%2 Portfolio

まだ CALL FAR AX の実験にたどり着けていないw この中では最初に書いた項目が興味深くて、命令実行後のシングルステップ発動前に外部割り込みが割り込むんだな、と。 この前見つけた書き込みでは、シングルステップのハンドラーの中で割り込み信号が来ると、IRET で割り込み許可になるとともに割り込みハンドラーに飛んでその入口でシングルステップ発動するという話だったので、割り込みチェックは命令実行前なのかなと思うんだけど、何がなんだか。

さて、TF に関する IRET と POPF の挙動の違いを見ていると、IRET で割り込み許可にした場合、次の命令を実行する前に外部割り込みが発生する場合があるとしか思えない。 それを検証する方法を考えていて、ひらめいた。 わざとフラグレジスターの予約ビットを異なる値にして IRET 命令を実行する。 そしてすぐ次の命令でスタックを読む。 割り込みが発生していたなら、予約ビットは固定値に戻るはずである。

というわけで、IRET で割り込み許可にすると直後の命令で割り込みが発生することが検証できた。TF=1 にした時の挙動とも整合性が保たれているし納得。8086 のマニュアルっぽい資料で、IRET も STI も、次の命令が終わるまで割り込みが発生しないと書かれているものがあったが、この実験結果からすればそれは間違いということになる。

2019/12/19 のコメントを読む・書く


Powered by Tomsoft Diary System 1.7.4

/var/log/hdk.log コメント一覧

トップ / 日記索引 / 日記 (2019 年 12 月中旬)

Hideki EIRAKU