読者です 読者をやめる 読者になる 読者になる

絶品ゆどうふのタレ

ふと気づいたことを綴るだけのメモ

8086命令セットの細かいメモ(2)

8086 assembler binary cpu

今日もまた、細かいけどためになる話を教えてもらったのでメモ。 自分で事後補足として調べたものも含むので、用語が正確じゃないかも。ツッコミ希望。

NASMがpushf(9C)/popf(9D)の機械語をpushfw/popfwとディスアセンブルするのはなぜか?

これはすごく歴史的経緯が深いやつで、16/32/64bitのCPU命令の拡張に伴う変更に起因するもの。 inc/dec命令その他複数の命令も同様の事情を持っている。

instruction prefix

この話に関係するのは、instruction prefix(命令プレフィックス)と呼ばれる、16/32/64bitの切り替えと互換保持などのために用いられる機能。

特に16/32bitの命令切り替えに関連してくるのは、

  • The operand-size prefix (66H)
  • The address-size prefix (67H)

といった、オペコードの前に置かれるprefix。これが配置されることで、その後ろの命令のオペランドサイズを切り替える。

pushf/popfにおける具体例

表題の疑問の回答。例えば、

bits 16
pushf
pushfw
pushfd

は、アセンブルすると

9C
9C
669C

となるが、

bits 32
pushf
pushfw
pushfd

は、

9C
669C
9C

となる。 逆アセンブルの場合も同様で、-b 16では

9C   pushfw
669C pushfd

だが、-b 32では

9C   pushfd
669C pushfw

という解釈になる。 ちなみに、16bit命令のpushf/popfと等価なものはpushfw/popfwであり、pushfd/popfdは32bit用命令セット。

64bitになると、32bit時代の命令であるpushfd/popfdは廃止され、64bit用にpushfq/popfqが加わる。

予想だが、16bitのものが残って32bitのものが消えたのは、 16bit機能がリアルモード/プロテクトモードの切り替えで意識する必要があるからではないか、と思っている(正解はまだ知らない)。

REXプレフィックス

64bit化の際には、このprefix以外に、さらにREX prefixが導入された。 その導入のために、inc/dec命令の領域を再配置し、その一部がprefix用に再利用されている。

同じ命令が複数の方法で表現可能な理由

例えば、

mov ax,0x12

は、以下の2通りで表現可能。

B012
C6C012

このように、なくなってもいい or 他の方法で表現できる命令が時々存在する。

何故こんなのがあるかというと、よく使われる命令セットを1つのショートカット機能で実現することでbyte数の節約に役立てる、というのが存在理由らしい。

ここは自分の推測だが、CISCの思想というのはつまり、こういうことなのかもしれない。メモリ大事。

addのImmediate to Register/Memory命令でs:w = 10が無い & s:w = 11でdataが1byteなのはなぜか

フラグの意味は以下のとおり。

  • s: signedの意。数値に+/-がつくアレ。
  • w: addの演算がbyteの演算かwordの演算か。

加算命令ではあるが、コンピューターの世界では桁あふれと補数の存在によって減算も行われる、というところまでが前提。

sフラグは、wordの世界での下桁1byte分の減算を実現している。 計算としてはsのフラグなしでも全て成り立つのだが、sを導入することで0XFFxxと加算する場合と比べて1byteが節約できる、というのが(おそらく)このフラグの目的で、同時にs:w = 11でdataが1byteだった理由。

そして、byteの演算にはsignedを持ち込む必要性がなかったために、s:w = 10の演算は定義されなかった、ということのようだ。

ざっくりまとめると

  • 1byte + 1byte なら引き算考えるときsignとか不要
  • 2byte + 2byte も同じくsign不要
  • 2byte + 1byte分の引き算をする時、signedで考えると1byteケチれる

という話。

ちょっとした感想

こうしてアセンブラ機械語の対比を見つつ歴史的経緯を知っていくと、一見なんだか意図の読めない命令セットの中の、CPUの進化・効率化と互換性確保のバランスを綱渡りしてる感じが垣間見えて、非常に面白い。

全命令セットを実装していくのは冗長な作業では、と最初は思ったけど、このへんを知るにつけ意味のある作業だと実感が強まってて良い。