2015-09-08 17 views
5

私はNASM使うマシン命令にいくつかのアセンブリ命令を変換しようとしたとき、私は何か面白いことを発見した、x86のISAで遊んでいます。同じアセンブリ命令が、別のマシン命令

mov [0x3412],al 
mov [0x3412], bl 
mov [0x3412], cl 
mov [0x3412], dl 

1 00000000 A21234     mov [0x3412], al 
2 00000003 881E1234    mov [0x3412], bl 
3 00000007 880E1234    mov [0x3412], cl 
4 0000000B 88161234    mov [0x3412], dl 

ご覧のとおり、mov [0x3412], alはルールの例外です。 はまた、私はmov [0x3412], alは、2つの異なるマシン命令にマッピングされました。

[email protected]:~/asm$ ndisasm 123 
00000000 88061234   mov [0x3412],al 
00000004 A21234   mov [0x3412],al 

この特別な命令に加えて、x86の複数のマシン命令にマッピングする他のアセンブリ命令がありますか?あなたが観察している何

+13

インテルの808Xデザインのアーティファクトに遭遇しました。 AXは一般的な16ビットレジスタですが、インテルはAX(またはAHとALのハイ/ロウの8ビットバージョン)をいくつかの操作に特化させました。 IntelはAXレジスタをアキュムレータとして認識しました。 AX(およびAH、AL)は、いくつかの命令に対して特殊なエンコーディングを持っています(通常、1バイト少ない)。より短いまたはより長い命令を使用することを選択できます(限られたメモリのほうが短い方が良い)。 AX/AH/ALには、MOV以外にADC、ADD、AND、CMP、OR、SBB、SUB、TEST、XORの特殊なエンコーディングがあります。 –

+4

@MichaelPetch:それは実際の答えであり、単なるコメントではありません! – usr2564301

+3

このようなことに興味があるなら、間違いなく命令セットのリファレンスを調べる必要があります。 – Jester

答えて

11

は、Intelが8088プロセッサで作られた設計上の考慮事項の一つの成果物です。 8088プロセッサとの互換性を維持するために、今日のx86ベースのプロセッサは、特に命令セットに関連する設計考慮事項のいくつかを引き継いでいます。特にインテルは、8088がパフォーマンスを犠牲にしてメモリの利用効率を上げるべきであると判断しました。彼らは、いくつかの命令のサイズを制限する特別なエンコーディングを持つ可変長のCISC命令セットを作成しました。これは、固定長命令を使用したが、より良い性能を達成することができる多くのRISCベースのアーキテクチャ(古いMotorola 88000など)とは異なります。それは小さい命令エンコーディングの一部を達成するために使用される複雑な可変長命令を復号化するプロセッサのためのより多くの時間を要するため

速度可変または固定長命令セットの間のトレードオフでした。これは、スペースの有効活用を実現するための考慮事項は、はるかに顕著であった(1980年頃)、古い文献ではインテル8088

のために本当でした。それはAXレジスタに関連する私の答えに記載されている情報は、しかし、情報の一部はthisのようなオンラインの記事で見つけることができ8088 Assembler Language Programming: The IBM PCと題した私の棚の上の本、から来ています。オンライン記事から

この情報は、AX(アキュムレータ)の状況とBX、CX、DXのような他の汎用レジスタに非常に適用されます。

AX「はアキュムレータ 『』である。

例えばMULとDIVなどの操作のいくつかは、オペランドの一方がアキュムレータであることを必要とするようADDのようないくつかの他の操作を、そしてSUB、レジスタのいずれかに適用される(すなわち、8一般 - 及び特殊目的レジスタのいずれかである)が、アキュムレータを操作するときに、より効率的であることができる。

BX「は基地 'レジスタであります;

それは間接アドレス指定のために使用することができるだけの汎用レジスタです。例えば、命令MOV [BX]、AXはAXの内容をアドレスがBXで与えられるメモリ位置に記憶させる。

CXは「カウント '' 登録。

ループ命令(LOOP、LOOPE、およびLOOPNE)、シフトされ、命令(RCL、RCR、ROL、ROR、SHL、SHRを回転させます、SAR)、文字列命令(接頭辞REP、REPE、およびREPNE)はすべて、繰り返し回数を決定するためにカウント・レジスタを使用します。

DX「は、データ 『』レジスタです。

それはワードサイズMULおよびDIV操作のためAXと一緒に使用され、そしてそれはまた、INとOUTのポート番号を保持することができます指示が、他の汎用レジスタのすべてがそうであるように、それは、データを格納するための便利な場所として主に利用可能である。

あなたはインテルが多様に使用される汎用レジスタを意図見ることができるようにしかし、彼らはまた、特定の目的のために使用することができ、しばしば関連する指示に特別な意味を持っていました。あなたのケースでは、AXアキュムレータと考えられています。インテルはこれを考慮に入れ、いくつかの命令では、完全な命令をより効率的に保存するために特殊なオペコードを追加しました。あなたは(AXと、AL)MOV命令でこれを見つけたが、それはまた、ADCADDANDCMPORSBBSUBTESTXORに適用されます。これらの命令のそれぞれは、1バイト少ないALを使用すると、より短いオペコード符号化を有する。あるいは、より長いオペコードでAX、ALをエンコードすることもできます。あなたの場合:

00000000 88061234   mov [0x3412],al 
00000004 A21234   mov [0x3412],al 

2つの異なるエンコードがありますが同じ命令ですか?

これは良いHTML x86 instruction set referenceですが、インテルはIA-32(i386など)と64ビットアーキテクチャでは非常に詳細なinstruction referenceを提供しています。

+2

もう一つの短い形式のopcodeの場合、 'rol/ror/rcl/rcr'の' imm8'バイトが保存されます。狂ったx86 CISCの奇妙さのおかげで、データに応じて1セットのOF(オーバーフローフラグ)を回転させますが、他のカウントで回転すると、未定義のままです。これは、 'C1 C0 01'(ロングフォーム' rol eax、1')ではなく、ショートフォームopcodeにのみ適用されます。http://agner.org/optimize/およびhttp://users.atw.huによると/instlatx64/GenuineIntel00506E3_Skylake_InstLatX64.txt、Intel IvyBridge、Haswell、およびSkylakeは、ロングフォームで2倍のスループットを持ちます。 SandyBridgeはどちらの形式でも2つのuopsをとります。たとえ 'count!= 1'でもあります。 –