x / 2 + 100 *(a + b)-3 /(c + d)+ e * eアセンブリ
次のアルゴリズムを記述します:x / 2 + 100 *(a + b)-3 /(c + d)+ e * e次のことを知っている:a、c-ワード、b、d-バイト、e-ダブルワード、x-qword
mov eax, dword [x]
mov edx, dword [x + 4] ; edx:eax = x
mov ebx, 2
idiv ebx ; eax = edx:eax / ebx = x / 2
mov ebx, eax ; save the result in ebx so we can do the other operations
mov al, [b]
cbw ; ax = b
add ax, [a] ; ax = a + b
mov dx, 100
imul dx ; dx:ax = ax * dx = 100 * (a + b)
push dx
push ax
pop eax ; 100 * (a + b)
add ebx, eax ; ebx = x / 2 + 100 * (a + b)
mov al, [d] ; al = d
cbw ; ax = d
add ax, word [c] ; ax = c + d
mov cx, ax ; cx = c + d
mov ax, 3
cwd
idiv cx ; ax = dx:ax / cx
cwd
push dx
push ax
pop eax ; eax = 3 / (c + d)
sub ebx, eax
mov eax, ebx
cdq ; edx:eax = x / 2 + 100 * (a + b) - 3 / (c + d)
mov ebx, eax
mov ecx, edx ; ecx:edx = x / 2 + 100 * (a + b) - 3 / (c + d)
mov eax, [e]
imul dword [e] ; edx:eax = e * e
add eax, ebx
adc edx, ecx
mov dword [result + 0], eax
mov dword [result + 4], edx
不必要に複雑にしましたか?
回答
次のアルゴリズムを記述します:x / 2 + 100 *(a + b)-3 /(c + d)+ e * e
a, c - word,
b, d - byte,
e - doubleword,
x - qword
最大数は64ビット(xはqword)であるため、最終結果も64ビットである必要があります。
最初の操作は、xのqwordを2で除算することでしたEBX。レジスタ内の商を移動したため、この結果は1つのdwordに収まると予想しているようです。この仮定を行うことはできません。さらに悪いことに、商が32ビットに収まらない場合、除算によって除算例外が簡単に発生する可能性があります。
解決策として、2で割ることは、実際には単に右にシフトするだけであることに注意する必要があります。
mov ebx, [x]
mov ebp, [x + 4] ; EBP:EBX is x
sar ebp, 1
rcr ebx, 1 ; EBP:EBX is x / 2
これは、他の計算をEBP:EBX使用に追加するには、他の計算もスケールアップする必要があることを意味します。
add ebx, ...
adc ebp, ...
加算は結合法則であるため、e * e部分を計算することから始めることができます。式を再配置せず、最終的にレジスタをさらに移動する必要がありました。大したことではありませんが、私のやり方はもっと良いです:
mov eax, [e]
imul eax
add ebx, eax
adc ebp, edx
次に100 *(a + b)が来る:
movsx eax, word [a]
movsx edx, byte [b]
add eax, edx ; eax = a + b
mov edx, 100
imul edx ; edx:eax = 100 * (a + b)
add ebx, eax
adc ebp, edx
3 /(c + d)はあなたにお任せします...
...そして最後に終わりは次のようになります:
sub ebx, eax
sbb ebp, edx
mov [result + 0], ebx
mov [result + 4], ebp
不必要に複雑にしましたか?
異なる操作の間に空白行を挿入しなかったため、プログラムを読むのは少し難しかったです。
関連するレジスタがすでにサイズを暗示している場合は、サイズタグ(バイト、ワード、dword)を書き込む必要はありません。
mov dword [result + 0], eaxDWORDタグ冗長です。プログラム内のコメントを互いに上に揃えるのが最善です。
次のようなタイプミスを避けるために、注意深く読み直してください。
mov ecx, edx ; ecx:edx = x / 2 + 100 * (a + b) - 3 / (c + d)する必要があります
ECX:EBX。正方形を計算するには:レジスタに数値をロードしたら、同じレジスタを乗算して、次のようにメモリを再度使用する必要はありません。
mov eax, [e] imul eax ; Don't write "imul dword [e]"