[解決済み] mul/divでcdqを拡張して署名するのはいつ、なぜか?
質問
今日のテストで、ダブルワードをクアッドワードに変換する問題だけがわからなかった。
そこで考えたのですが、乗算や除算で符号を伸ばすのはなぜか、いつなのか?また、cdqのような命令はいつ使うのでしょうか?
解き方は?
使用方法
cdq
/
idiv
符号付き32ビット/32ビット=> 32ビット除算の場合。
xor edx,edx
/
div
を無記名にします。
EAXで配当を開始し、DIVまたはIDIVにオペランドとして除数を指定した場合。
mov eax, 1234
mov ecx, 17
cdq ; EDX = signbit(EAX)
idiv ecx ; EAX = 1234/17 EDX = 1234%17
EDX/RDX をゼロにしてから EDX:EAX に符号拡張した場合。
idiv
,
のように、-5 / 2 に対して大きな正の結果を得ることができます。
.
32ビット除算は、64/32ビットのフルパワーで実行できますが、商がオーバーフローしないように除数が十分に大きいことが分かっていなければ、安全ではありません。 (つまり、一般的には
(a*b) / c
のみで
mul
/
div
と、EDX:EAXに64bitのテンポラリーがあります)。
除算は商のオーバーフローで例外(#DE)を発生させる。 Unix/Linuxの場合。
カーネルはSIGFPEを送出します。
除算エラーを含む算術例外の場合。 通常の符号またはゼロ拡張除算では、オーバーフローは以下の場合にのみ発生します。
と
idiv
の
INT_MIN / -1
(すなわち、最も負の数の2の補数の特殊な場合)。
insn refのマニュアルを見ればわかるように( x86 タグのwiki)をご覧ください。
-
ワンオペ
mul
/imul
:edx:eax = eax * src
-
ツーオペランド
imul
:dst *= src
. 例imul ecx, esi
は eax や edx の読み書きをしません。
-
div
/idiv
分割edx:eax
のsrc.商で計算されます。eax
の余りedx
. の形はありません。div
/idiv
を無視したedx
を入力します。 -
cdq
サインエクステンドeax
にedx:eax
の符号ビットをブロードキャストする。eax
の各ビットにedx
. と混同しないようにcdqe
をよりコンパクトにした64ビット命令です。movsxd rax, eax
.元々(8086)は、ちょうど
cbw
(ax = sign_extend(al)
) とcwd
(dx:ax = sign_extend(ax)
). x86 の 32bit と 64bit への拡張により、ニーモニックが若干曖昧になっています (しかし、覚えておいてほしいのは、他のcbw
で終わり、eax 内のバージョンは常にe
Extendの場合)。 8bitのmulとdivは特殊なので、dl=sign_bit(al)命令はありません。ax
の代わりにdl:al
.
への入力は
[i]mul
はシングルレジスタであるため、何もする必要がありません。
edx
乗算の前に
入力が符号付きの場合、符号拡張して乗算の入力として使用するレジスタを満たします。
movsx
または
cwde
(
eax = sign_extend(ax)
). 入力が符号なしであれば、ゼロ拡張します。 (ただし、例えば、乗算結果の下位16ビットだけが必要な場合は例外です。
のどちらか、あるいは両方の入力の上位16ビットがゴミであっても問題ではありません。
.)
除算の場合、常にeaxをゼロにするか、符号拡張してedxに入れる必要があります。 ゼロ拡張は、無条件にedxをゼロにするのと同じなので、特別な命令はありません。 ただ
xor edx,edx
.
cdq
よりもずっと短いので、存在するのです。
mov edx, eax
/
sar edx, 31
で、eaxの符号ビットをedxの各ビットにブロードキャストします。 また、即時カウント > 1 のシフトは 186 年まで存在せず、まだカウントごとに 1 サイクルだったので、8086 ではさらに悪いことをしなければなりませんでした(分岐するか、符号ビットを一番下に回転して + を分離するなど)。
neg
ということです。) そこで
cwd
8086では、必要なときに多くの時間やスペースを節約することができました。
64bitモードでは、32bitの値を64bitに拡張する符号と0が一般的です。 ABIは32bitの値を保持する64bitレジスタの上位32bitにゴミを入れることを許可しているため、もし関数が
edi
を使用することはできません。
[array + rdi]
を使用して配列のインデックスを作成します。
そのため、多くの
movsx rdi, edi
(符号拡張)、または
mov eax, edi
(ゼロ拡張。Intel mov-eliminationが動作しないため、別のターゲットレジスタを使用する方が効率的です。
mov same,same
)
関連
-
[解決済み】バイナリーボム - フェーズ4
-
[解決済み】lc3 LDR命令と格納される値について
-
[解決済み】x86アセンブリ。AT&Tの構文で「subl」コマンドはどのように動作するのか
-
[解決済み] MIPSでディブディブ
-
[解決済み] MIPS srlを変数で指定
-
[解決済み] なぜSet on Less ThanはALU演算なのか?
-
[解決済み] ARMv8でリテラル0ではなく、xzrレジスタを使用するのはなぜですか?
-
[解決済み] cmp命令の理解
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
-
[解決済み] 32ビットレジスタに対するx86-64命令は、なぜフル64ビットレジスタの上部をゼロにするのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】MIPSで整数の絶対値?
-
[解決済み] MIPs Assemblyでsllなどを使ってビットをずらすのはなぜですか?
-
[解決済み] MIPS分岐実行順序(beqz)
-
[解決済み] アセンブリ命令のトラップは何をするのですか?
-
[解決済み] x86 8086 アセンブリで 0-9 の範囲の乱数を生成する。
-
[解決済み] 8086アセンブリ言語での2つのレジスタのスワッピング(16ビット)
-
[解決済み] アセンブリ言語 新規ライン
-
[解決済み] アセンブリMIPS .ALIGNとメモリアドレスの理解
-
[解決済み] ワードptrとは何ですか?
-
[解決済み] ESPレジスタとEBPレジスタとは何ですか?