x86 Instruction Prefix Bytes - HobbyOSs/opennask GitHub Wiki
- 参考: Google Group - 66H and 67H override prefixes.
- 参考: Real Mode
- 参考: X86-64 Instruction Encoding: Operand-size and address-size override prefix
- 参考: Tips IA32(x86)汎用命令一覧 補足
さらっと紹介されているけどわからんので、特に 0x66
, 0x67
について
32bitモードの最初の2バイトはOverride prefixesと呼ばれる。なぜならそれらは常に存在するとは限らないからだ。 最初の1バイト目(0x67)は命令に使われるオペランドのアドレスのサイズを変更する。 次の2バイト目(0x66)はオペランドサイズを変更する。
この規則はわりとどこでも適用されるのだが、インテルの仕様ドキュメントに記載があまりない。
- はじめて読む486 のp.164~166に色々と載っていたので、その情報とWEBの情報をもとにまとめる
アドレスサイズとは
アドレスサイズとはアセンブラ命令が扱うメモリのサイズのこと
MOV AX, [0x1234] ; これは16bitサイズなのでアドレスサイズ16bit
MOV AX, [SI] ; これは16bitサイズなのでアドレスサイズ16bit
MOV AX, [0x12345678] ; これは32bitサイズなのでアドレスサイズ32bit
MOV AX, [ESI] ; これは32bitサイズなのでアドレスサイズ32bit
オペランドサイズとは
オペランドサイズとはアセンブラ命令が扱う数値のサイズのこと
MOV AX, 0x1234 ; これは16bitサイズなのでオペランドサイズ16bit
MOV EAX, 0x12345678 ; これは32bitサイズなのでオペランドサイズ32bit
アドレスサイズとオペランドサイズのおさらい
オペランドサイズ16bit | オペランドサイズ32bit | |
---|---|---|
アドレスサイズ16bit | MOV AX, [BX] |
MOV EAX, [BX] |
アドレスサイズ32bit | MOV AX, [EBX] |
MOV EAX, [EBX] |
以下のことがわかる
- オペランドサイズはメモリーアドレス表現関係なしにレジスタと即値を見てやれば決まる
- アドレスサイズはメモリーアドレス表現のみ見てやれば決まる
そして、デフォルトのモードは16bit命令モード/32bit命令モードのどちらかで決まる
0x67(アドレスサイズ・プレフィックス)
- もし、CPUが16bit命令モードとして(プロテクトモードのみ)動き、メモリーアドレス表現に32bitレジスタが使われていれば
- ➔ Address-size prefixは無視される。(※naskではこの場合0x67は機械語として付与されない)
- もし、32bit命令モードでメモリーアドレス表現に16bitレジスタが現れるのであれば、
- ➔ 16bitレジスタを選択するためにAddress-size prefixが現れる。
0x66(オペランドサイズ・プレフィックス)
- Pentium IIで80386が16bit命令モードとして(リアルモードもしくはプロテクトモード)動く
- 32bitレジスタが使われていれば、 Operand-size prefixes(0x66) が命令の前に付加される。
逆に、
- リアルモードで32bitのアドレッシング・モードを使うことが出来る、それは命令の最初に Operand-size prefix を付加することで可能だ
機械語の概略
(a) 16-bit instruction mode
_________ ___________ ____________ _________
| Opcode ||MOD-REG-R/M||Displacement||Immediate|
| || || ||0-4 bytes|
|1-2 bytes|| 0-1 bytes || || |
| || || || |
| || || || |
--------- ----------- ------------ ---------
(b) 32-bit instruction mode (80386 through Pentium 4 only)
........ ........ _________ ___________ ......... __________________
:Address ::Operand :| Opcode ||MOD-REG-R/M|:Scaled :|Displace-||Immediate|
:size ::size :| || |:Index :|ment ||0-4bytes |
:0-1bytes::0-1bytes:|1-2 bytes|| 0-1 bytes |:0-1 bytes:| || |
:Prefix :: :| || |: :| || |
:67H ::66H :| || |: :| || |
'''''''' '''''''' --------- ----------- ''''''''' ------------------
実例
- (1)
[BITS 32]
を宣言してないので16bit命令モードである
; プロテクトモード移行
[INSTRSET "i486p"] ; 486の命令まで使いたいという記述
MOV ECX,[EBX+16] ; 0x67 0x66 0x8b 0x4b 0x10
-
0x67
16bit命令モード
かつメモリーアドレス表現に32bitレジスタが使われている
よって0x67
を付加
-
0x66
16bit命令モード
かつ32bitレジスタを使っている
よって0x66
を付加
-
(2)
[BITS 32]
を宣言している
[BITS 32]
[INSTRSET "i486p"]
MOV ECX,[ESP+4] ; 0x8b, 0x4c, 0x24, 0x04
MOV AL,[ESP+8] ; 0x8a, 0x44, 0x24, 0x08
0x67
32bit命令モード
で32bitレジスタが使われている
よって0x67
は不要
0x66
32bit命令モード
なので0x66
は不要