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

なんとな~くしあわせ?の日記

ClojureとかAWSの設定とかをメモする技術ブログ

x86オペコード命令の解析 ModR/M の解説

アセンブラ


x86 OpCode Instruction Decoding

これの和訳です。

stackoverflow.com

I've been looking into the Software Developer's Manual of the x86 architecture trying to brush my reverse engineering skills. I know that the architecture is complex and backwards compatible with previous generations. With newer generations some of the older documentation parts get left out. But one of the disturbing explanations and misinterpretations were instructions similar to this one:

わたしはx86アーキテクチャのソフトウェア開発者マニュアルにあたって、自らのリバースエンジニアリングスキルを高めているところなのです*1。そのアーキテクチャは複雑で過去のバージョンとの上位互換性があるものと知っています。新しい世代について言えば、そのうちの古いドキュメントを省略しています。その中でもイライラさせるような説明と誤解は、これに似たような命令の説明にある*2

80 /2 ib

So instructions based on the following 80 OpCode would be followed by a MOD/RM/REG byte. One of the side affects of disregarding old content, I had no clue about different versions MOD/RM/REG byte. But I always assumed their was a difference due to the architectural roots being 8/16-bit. Thankfully I stumbled on the dissection of the MOD/RM/REG byte during the original introduction of the architecture.

So instructions as the one provided above followed by the forward slash digit says that the Octal value would be contained within the RM offset of the MOD/RM/REG byte would be a value of 2.

つまりは、0x80のオペコードに基づいた命令の後にはMOD/RM/REGが従う。古い内容を無視することで起こる副次効果の一つは、わたしはMOD/RM/REGの異なる形式について手がかりが全然ないということだ。しかし、わたしはいつもそのアーキテクチャの根源が8/16bitベースの構造であるとためにその差異が存在すると仮定している。ありがたいことに、わたしは元々のアーキテクチャの入門中、MOD/RM/REGの解剖に躓いた。

命令に続くスラッシュと数字が提供するところのものが言うには、その8進数はMOD/RM/REGのうちRMの中に包含されるはずで、今回それの値は2であるのだ。

My actual question(s) are the following:

Does the MOD offset in MOD/RM/REG byte accept all addressing modes in the current condition or are there any imposed restrictions? The other thing does anybody have a clue why the digit is specified with a /2? Would that be a reason to assume that lower values were used in older generations of the ISA and thus are preserved for backwards compatibility.

わたしの実際的な質問は以下のようなものだ:

MOD/RM/REGのうちMODのオフセットは現在の状況ですべてのアドレッシング・モードを許容するのか?もしくはそこにあるかもしれない制約によって制限されるのか?
もうひとつは、なぜ数値が/2で指定されるのか?
古い命令セットの中でより低い数値が使われており、そのために後方互換を確保するために、そのようになっているという仮定は妥当だろうか?

80 /2 ib 記法部分に関するコメント

/2 refers to the value of reg field of ModRM byte. reg field has size of 3 bits (bits 3..5).
In AMD manual Vol 3: /n A ModRM-byte reg field or SIB-byte base field, where n is a value between zero (binary 000) and 7 (binary 111).

ib means immediate byte.
In 16-bit code

/2はModRMのうちregの値を参照している。regは3bitのサイズをもつ(bitは3~5)。
AMDマニュアルの3巻から:
/n は ModRMのreg部分を指すか、SIBの部分を指す。
そこにおいて、nは0(000)〜7(111)までの値をとる。

ibは即値を意味する。16bitのコードにおいて:

80 00 00 is add byte [bx+si], 0x0,
80 08 00 is or  byte [bx+si], 0x0,
80 10 00 is adc byte [bx+si], 0x0,
80 18 00 is sbb byte [bx+si], 0x0,
80 20 00 is and byte [bx+si], 0x0,
80 28 00 is sub byte [bx+si], 0x0,
80 30 00 is xor byte [bx+si], 0x0, 
and 
80 38 00 is cmp byte [bx+si], 0x0. 

実際例によるサンプル1

naskで以下のコードをアセンブルすると、

CMP CL,18

こうなります

80 f9 12

CMPの定義を見てみると、CLは8bit用レジスタなので、以下のオペコードになるはず*3

0x80 /7 ib

です

0x800x12(10進数で18)は自明ですね。残る0xf9を2進数にすると:

ここも見て

Assembly Programming on x86-64 Linux (06)


ModRMの仕様に従って、ビットをmod/reg/'r/m' に分解。


----------------------
11111001 -> 11/111/001
----------------------
[mod] 11 : レジスタを指定してるだけなので11
[reg] 111: /7 で指定された通り、全てのビットが立っている
[r/m] 001: 下の表で指定された通り, CLを指定している

* 80x86 Opcodes: 
https://courses.engr.illinois.edu/ece390/resources/opcodes.html
-------------------
000 : AL : AX : EAX 
001 : CL : CX : ECX 
010 : DL : DX : EDX 
011 : BL : BX : EBX 
100 : AH : SP : ESP 
101 : CH : BP : EBP 
110 : DH : SI : ESI 
111 : BH : DI : EDI
------------------- 

実際例によるサンプル2

naskで以下のコードをアセンブルすると、

CMP SI,5

こうなります

83 fe 05

SIは16bit用レジスタなので、以下のオペコードになるはず。

0x83 /7 ib

です

0x830x05は自明ですね。残る0xfeを2進数にすると:

----------------------
11111110 -> 11/111/110
----------------------
[mod] 11 : レジスタを指定してるだけなので11
[reg] 111: /7 で指定された通り、全てのビットが立っている
[r/m] 110: 下の表で指定された通り, SIを指定している

* 80x86 Opcodes: 
https://courses.engr.illinois.edu/ece390/resources/opcodes.html
-------------------
000 : AL : AX : EAX 
001 : CL : CX : ECX 
010 : DL : DX : EDX 
011 : BL : BX : EBX 
100 : AH : SP : ESP 
101 : CH : BP : EBP 
110 : DH : SI : ESI 
111 : BH : DI : EDI
------------------- 

*1:意識高いな〜

*2:なかなかこなれた日本語にならない。察して。

*3:IA32(x86)汎用命令一覧 Cから始まる命令 CMP命令