Intel x86 Assembly Language & Microarchitecture
制御フロー
サーチ…
無条件ジャンプ
jmp a_label ;Jump to a_label
jmp bx ;Jump to address in BX
jmp WORD [aPointer] ;Jump to address in aPointer
jmp 7c0h:0000h ;Jump to segment 7c0h and offset 0000h
jmp FAR WORD [aFarPointer] ;Jump to segment:offset in aFarPointer
相対的な近点ジャンプ
jmp a_labelは次のjmp a_labelです。
- 近く
宛先の論理アドレスのオフセット部分のみを指定します。セグメントはCSと仮定する。 - 相対
命令セマンティックは、次の命令アドレスまたはIP = IP + relからジャンプrelバイト1を転送します。
命令は、 EB <rel8>またはEB <rel16/32>いずれかとしてエンコードされます。アセンブラは、最も適切な形式を選択します。
例えばNASM jmp SHORT a_label 、 jmp WORD a_label 、 jmp DWORD a_labelなどのアセンブラオーバーライドが可能です。
絶対間接近点ジャンプ
jmp bxとjmp WORD [aPointer]は次のとおりです。
- 近く
これらは、宛先の論理アドレスのオフセット部分のみを指定します。セグメントはCSと仮定する。 - 絶対間接
命令の意味は、 regまたはmemのアドレス、またはIP = reg、IP = memジャンプします。
命令はFF /4として符号化され、間接的にはオペランドのサイズは他のすべてのメモリアクセスについて決定される。
絶対遠いジャンプ
jmp 7c0h:0000hは:
遠い
論理アドレスの両方の部分、セグメントとオフセットを指定します。absolute命令のセマンティックは、アドレスセグメント:offsetまたは
CS = segment, IP = offsetジャンプします。
命令は、コードサイズに応じてEA <imm32/48>としてエンコードされます。
いくつかのアセンブラで2つの形式の中から選択することができます。例えば、NASM jmp 7c0h: WORD 0000hとjmp 7c0h: DWORD 0000hは第1と第2の形式を生成します。
絶対間接遠距離ジャンプ
jmp FAR WORD [aFarPointer]は次のとおりです。
farこれは、 論理アドレスの両方の部分、つまりセグメントとオフセットを指定します。
Absolute indirect命令の意味は、 mem 2または
CS = mem[23:16/32], IP = [15/31:0]格納されているセグメント:オフセットにジャンプします。
命令はFF /5として符号化され、オペランドのサイズはサイズ指定子を有するコントローラとすることができる。
NASMでは直感的ではありませんが、 16:16オペランドの場合はjmp FAR WORD [aFarPointer] 、 16:32オペランドの場合はjmp FAR DWORD [aFarPointer]です。
行方不明のジャンプ
近くの絶対
間接的に近いジャンプでエミュレートできます。mov bx, target ;BX = absolute address of target jmp bx遠い親戚
とにかく使用感が無く、狭すぎます。
1 2つの補数を使用して、符号付きオフセットを指定し、したがって後方にジャンプします。
2サイズ16:16と16:32の seg16:off16またはseg16:off32になります。
試験条件
条件ジャンプを使用するには、条件をテストする必要があります。ここでの条件のテストは 、フラグをチェックする行為のみを参照し、実際のジャンプは条件ジャンプで説明します。
x86は、EFLAGSレジスタに頼って条件をテストします。EFLAGSレジスタは、各命令が設定できるフラグのセットを保持します。
subやaddような算術命令and 、 xorやandなどの論理命令は明らかに「フラグを設定する」。これは、フラグCF 、 OF 、 SF 、 ZF 、 AF 、 PFがそれらの命令によって変更されることを意味する。どの命令でもフラグを変更することができます。たとえば、 cmpxchgはZFを変更します。
特定の命令によってどのフラグが変更されているかを知るには、命令参照を常にチェックしてください。
x86には、以前に言及した一連の条件付きジャンプがあり 、一部のフラグが設定されているか、一部がクリアまたはその両方である場合にのみジャンプします。
フラグ
算術演算と論理演算は、フラグの設定に非常に便利です。たとえば、 sub eax, ebxというsub eax, ebx後で、今度は符号なしの値を保持しているとします。
| 旗 | 設定時 | クリア時 |
|---|---|---|
| ZF | 結果がゼロの場合。 EAX - EBX = 0⇒EAX = EBX | 結果がゼロでない場合。 EAX - EBX≠0⇒EAX≠EBX |
| CF | 結果がMSbのために運ぶ必要があったとき。 EAX - EBX <0⇒EAX <EBX | 結果がMSbのためにキャリーを必要としなかったとき。 EAX - EBX≮0⇒EAX≮EBX |
| SF | 結果MSbがセットされたとき。 | 結果MSbがセットされていない場合。 |
| の | 署名付きオーバーフローが発生したとき。 | 署名付きオーバーフローが発生しなかったとき。 |
| PF | 結果の最下位バイトに設定されているビット数が偶数の場合。 | 結果の最下位バイトに設定されたビット数が奇数の場合。 |
| AF | 下位のBCD桁がキャリーを生成したとき。 それはビット4のキャリーです。 | 下BCD桁はキャリーを生成しなかったとき。 それはビット4のキャリーです。 |
非破壊検査
subおよびand命令は、デスティネーションオペランドを変更し、デスティネーションを変更しないように2つの余分なコピー(セーブおよびリストア)を必要とします。
非破壊テストを実行するには、 cmpとtestという命令がありtest 。 操作の結果が破棄され、フラグのみが保存されることを除いて、それらは破壊的な対応と同じです。
| 破壊的な | 非破壊的 |
|---|---|
sub | cmp |
and | test |
test eax, eax ;and eax, eax
;ZF = 1 iff EAX is zero
test eax, 03h ;and eax, 03h
;ZF = 1 if both bit[1:0] are clear
;ZF = 0 if at least one of bit[1:0] is set
cmp eax, 241d ;sub eax, 241d
;ZF = 1 iff EAX is 241
;CF = 1 iff EAX < 241
署名付きおよび無署名テスト
CPUは値1を登録するための特別な意味を与えません。signはプログラマの構造体です。 符号付きおよび符号なしの値をテストするときに違いはありません。プロセッサは、オペランドが符号付きおよび符号なしとみなされる場合は、通常の算術関係(等しい、より小さい、より大きいなど)をテストするのに十分なフラグを計算します。
1 2の補数のような特定のフォーマットでしか意味をなさない命令がいくつかありますが、これは、ソフトウェアでのアルゴリズムの実装に多くのコードが必要となるため、コードをより効率的にするためです。
条件付きジャンプ
フラグの状態に基づいて、CPUはジャンプを実行または無視することができます。フラグに基づいてジャンプを実行する命令は、 Jcc - Jump on Condition Code 1という一般名の下にあります。
同義語と用語
アセンブリコードの読みやすさを向上させるために、インテルは同じ条件コードに対していくつかの同義語を定義しました。たとえば、 jae 、 jnb 、およびjncはすべて同じ条件コードCF = 0です。
命令名は、それを使用したりしないようにするときに非常に強力なヒントを与えるかもしれないが、唯一の意味のあるアプローチがテストされ、 その後、適切な指示を選択する必要がフラグを認識することです。
インテルはcmp命令の後に使用すると完全な意味を持つ命令名を与えました。この説明の目的のために、 cmpは条件ジャンプの前にフラグを設定したものとみなされます。
平等
ZFが設定されている場合、オペランドは等しくなります。等価性をテストするには、 ZF = 1が必要です。
je a_label ;Jump if operands are equal
jz a_label ;Jump if zero (Synonym)
jne a_label ;Jump if operands are NOT equal
jnz a_label ;Jump if not zero (Synonym)
| 命令 | フラグ |
|---|---|
je 、 jz | ZF = 1 |
jne 、 jnz | ZF = 0 |
より大きい
符号なしオペランドの場合、桁上げが必要ない場合、つまりCF = 0の場合、宛先はソースよりも大きくなります 。 CF = 0の場合、オペランドが等しい可能性があり、 ZFをテストすると曖昧さがなくなります。
jae a_label ;Jump if above or equal (>=)
jnc a_label ;Jump if not carry (Synonym)
jnb a_label ;Jump if not below (Synonym)
ja a_label ;Jump if above (>)
jnbe a_label ;Jump if not below and not equal (Synonym)
| 命令 | フラグ |
|---|---|
jae 、 jnc 、 jnb | CF = 0 |
ja 、 jnbe | CF = 0、ZF = 0 |
符号付きオペランドの場合、符号付きオーバーフローが発生していない限り、 SF = 0であることを確認する必要があります 。この場合、 SFが反転します。符号付きオーバーフローが発生しなければOF = 0で 、それ以外の場合は1であるため、 SF = OFであることを確認する必要があります。
ZFは厳密/非厳密テストを実装するために使用できます。
jge a_label ;Jump if greater or equal (>=)
jnl a_label ;Jump if not less (Synonym)
jg a_label ;Jump if greater (>)
jnle a_label ;Jump if not less and not equal (Synonym)
| 命令 | フラグ |
|---|---|
jge 、 jnl | SF = OF |
jg 、 jnle | SF = OF、ZF = 0 |
未満
これらは上記の逆の条件を使用します。
jbe a_label ;Jump if below or equal (<=)
jna a_label ;Jump if not above (Synonym)
jb a_label ;Jump if below (<)
jc a_label ;Jump if carry (Synonym)
jnae a_label ;Jump if not above and not equal (Synonym)
;SIGNED
jle a_label ;Jump if less or equal (<=)
jng a_label ;Jump if not greater (Synonym)
jl a_label ;Jump if less (<)
jnge a_label ;Jump if not greater and not equal (Synonym)
| 命令 | フラグ |
|---|---|
jbe 、 jna | CF = 1またはZF = 1 |
jb 、 jc 、 jnae | CF = 1 |
jle 、 jng | SF!= OFまたはZF = 1 |
jl 、 jnge | SF!= OF |
特定のフラグ
各フラグは、 j<flag_name>で個別にテストできます.flag_nameには後続のF ( CF → C 、 PF → Pなど )が含まれていません。
前に説明しなかった残りのコードは次のとおりです。
| 命令 | 旗 |
|---|---|
js | SF = 1 |
jns | SF = 0 |
jo | OF = 1 |
jno | OF = 0 |
jp 、 jpe (e =偶数) | PF = 1 |
jnp 、 jpo (o =奇数) | PF = 0 |
1つの条件付きジャンプ(余分なもの)
特別なx86条件ジャンプの1つでは、フラグをテストしません。代わりに、現在のCPUアドレスモードが16または32ビットであるcxまたはecxレジスタのテスト値を実行し、レジスタがゼロを含むときにジャンプが実行されます。
この命令は、 カウンタレジスタ (の検証のために設計されたcx/ecx )前方のrep様の命令、又は前方のloopループ。
jcxz a_label ; jump if cx (16b mode) or ecx (32b mode) is zero
jecxz a_label ; synonym of jcxz (recommended in source code for 32b target)
| 命令 | レジスタ(フラグではない) |
|---|---|
jcxz 、 jecxz | cx = 0(16bモード) |
jcxz 、 jecxz | ecx = 0(32bモード) |
1そういうものか。
算術関係をテストする
符号なし整数
より大きい
cmp eax, ebx
ja a_label
それ以上
cmp eax, ebx
jae a_label
未満
cmp eax, ebx
jb a_label
以下
cmp eax, ebx
jbe a_label
等しい
cmp eax, ebx
je a_label
等しくない
cmp eax, ebx
jne a_label
符号付き整数
より大きい
cmp eax, ebx
jg a_label
それ以上
cmp eax, ebx
jge a_label
未満
cmp eax, ebx
jl a_label
以下
cmp eax, ebx
jle a_label
等しい
cmp eax, ebx
je a_label
等しくない
cmp eax, ebx
jne a_label
a_label
上記の例では、 a_labelは、テストされた条件が "true"の場合のCPUのターゲット先です。テストされた条件が "偽"の場合、CPUは条件ジャンプに続く次の命令を続行します。
類義語
命令のシノニムは、コードの可読性を向上させるために使用できます。
例えば、 jaとjnbe (Jump non jnbe equal)は同じ命令です。
署名付きのコンパニオンコード
| 操作 | 署名なし | 署名された |
|---|---|---|
| > | ja | jg |
| > = | jae | jge |
| < | jb | jl |
| <= | jbe | jle |
| = | je | je |
| ≠、!=、<> | jne | jne |