アセンブリ
ここでの話は、特に明記しない限り、linux/x86環境下での話である
操作の対象(operand)
ソースオペランド:入力
ディスティネーションオペランド:出力
EFLAGSレジスタ
https://gyazo.com/f7bc089e56df22ab8c43eb4639bc3915
0. CF : キャリーフラグ。最後の算術演算操作で加算においてレジスタの大きさを越えてビットのキャリー(桁上がり)かボロー(桁借り)をした場合にセットされる。これは、キャリーの生じた加算やボローの生じた減算の次の操作がされた場合に、1個のレジスタだけ扱うことのできる値であるか確認するのに使われる。
2. PF : パリティフラグ。結果の最下位バイトに値1 のビットが偶数個含まれている場合にセットされ、奇数個の場合にはクリアされる。
4. AF : 調整フラグ。2進化10進 (BCD) 演算の算術演算でキャリーまたはボローが生じたらセットされる。
6. ZF : ゼロフラグ。演算の結果がゼロ (0) になった場合にセットされる。演算結果がゼロ(全部のビットが0)のとき1,それ以外のとき0になる.
7. SF : 符号フラグ。操作の結果が負となった場合にセットされる。
8. TF : トラップフラグ。ステップバイステップのデバッギングをする場合にセットする。
9. IF : 割り込み可能フラグ。割り込みを有効化したい場合にセットする。
10. DF : 方向フラグ。ストリームの方向を制御する。セットするとストリング命令においてポインタがデクリメントされる(通常はインクリメントされる)。
11. OF : オーバーフローフラグ。符号付き算術演算の結果がレジスタに格納できないほど大きい値になった場合にセットされる。
12-13. IOPL : I/O特権レベルフィールド(2ビット)。現在のプロセスのI/O特権レベルを示す。
14. NT : ネストタスクフラグ。割り込みチェーンを制御する。現在のプロセスが次のプロセスにリンクされている場合にセットされる。
16. RF : 再開フラグ。デバッグ例外への応答を制御する。
17. VM : 仮想8086モード。8086互換モードにある場合にセットされる。
18. AC : アラインメントチェックフラグ。メモリチェックでアラインメントチェックが有効な場合にセットされる。
19. VIF : 仮想割り込みフラグ。IFの仮想イメージ。
20. VIP : 仮想割り込み保留フラグ。割り込みが保留されている場合にセットされる。
21. ID : 識別フラグ。セットできればCPUID命令がサポートされる。
レジスタ
rsp は 汎用レジスタ兼スタックポインタ
EAXレジスタは、RAXレジスタの下位32ビット
EIP(インストラクションポインタレジスタ) 次に実行するアセンブリ命令のアドレスを格納
MOVZX
インテル表記
インテル表記は、WindowsアセンブラやMicrosoft Visual Studioで使用されます。この表記法では、ソースと宛先の順序がAT&T表記と異なります。
mov eax, 1 ; eaxに1を格納する
add ebx, eax ; eaxの値をebxに加算する
インテル表記は [A] <- [B]
つまり [ディスティネーションオペランド] <- [ソースオペランド]
AT&T表記
AT&T表記は、GNUアセンブラやUnix系OSで使用されます。この表記法では、ソースと宛先の順序がインテル表記に対して逆転しています。
movl $1, %eax # %eaxに1を格納する
addl %eax, %ebx # %eaxの値を%ebxに加算する
AT&T表記は [A] -> [B]
つまり [ソースオペランド] -> [ディスティネーションオペランド]
高速化
以下の情報は検証中のものなので、鵜呑みにしないように
eflagsが変更される条件
add命令で結果が負の値になった時
[CF AF SF]が立ち、[ZF]が消える?
imul命令で結果が桁溢れしない程度の正の整数値になった時
[CF AF SF ZF]が消える?
[PF IF]はそのまま?
cmp命令
https://gyazo.com/479818af181ee3919fe3fdbcf8ef94c4
値が同じなら1をrexにセット
code:eq.asm
pop rdi
pop rax
cmp rax, rdi
sete al
movzb rax, al
値が 異なる なら1をrexにセット
code:neq.asm
pop rdi
pop rax
cmp rax, rdi
setne al
movzb rax, al
rax < rdi なら1をrexにセット
code:neq.asm
pop rdi
pop rax
cmp rax, rdi
setl al
movzb rax, al
rax <= rdi なら1をrexにセット
code:neq.asm
pop rdi
pop rax
cmp rax, rdi
setle al
movzb rax, al
動作
cmp命令は、次のように動作します:
オペランド1からオペランド2を減算します。
結果は破棄されますが、フラグレジスタが設定されます。
フラグの設定
ZF (Zero Flag): 結果がゼロの場合にセットされます。
SF (Sign Flag): 結果が負の場合にセットされます。
CF (Carry Flag): 借りが発生した場合にセットされます(無符号比較)。
OF (Overflow Flag): 符号付きオーバーフローが発生した場合にセットされます。
例
code:asm.asm
section .data
val1 db 10
val2 db 20
section .text
global _start
_start:
mov al, val1 ; ALレジスタにval1の値をロード cmp al, val2 ; ALとval2を比較 ; 比較結果に基づいてジャンプ
je equal ; 等しい場合
jl less ; ALがval2より小さい場合
jg greater ; ALがval2より大きい場合
equal:
; 等しい場合の処理
; ...
jmp end
less:
; 小さい場合の処理
; ...
jmp end
greater:
; 大きい場合の処理
; ...
jmp end
end:
; プログラム終了
mov eax, 1 ; システムコール番号 (sys_exit)
xor ebx, ebx ; ステータス 0
int 0x80 ; システムコールを呼び出し
この例では、val1とval2の値を比較し、その結果に基づいて異なるラベルにジャンプします。cmp命令は、条件付きジャンプ命令(je, jl, jgなど)と組み合わせて使用されることが一般的です。
jne命令 ZF(ゼロフラグ)が立っていないとき(=クリアされている, =0) にジャンプする
jne命令は、ゼロフラグ(ZF)がクリアされている場合にジャンプを行います。ゼロフラグがクリアされているということは、前の比較命令で比較された2つの値が等しくないことを意味します。
cqo命令を使うと、RAXに入っている64ビットの値を128ビットに伸ばしてRDXとRAXにセットする。
関数呼び出し