x / 2 + 100 * (a + b) - 3 / (c + d) + e * e montajda

Oct 21 2020

x / 2 + 100 * (a + b) - 3 / (c + d) + e * e için bir algoritma yazın: a, c - word, b, d - byte, e - doubleword, 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

gereksiz yere karmaşık hale mi getirdim?

Yanıtlar

6 SepRoland Oct 22 2020 at 03:52

için bir algoritma yazın: x / 2 + 100 * (a + b) - 3 / (c + d) + e * e

a, c - word,
b, d - byte,
e - doubleword,
x - qword

En büyük sayınız 64 bit olduğu için ( x bir qword), nihai sonucunuz da 64 bit olmalıdır!

İlk operasyon içinde QWORD bölmek oldu x Sen de katsayısı taşıdığınız çünkü bu sonuç sadece tek dword arasında yerini almasını beklemek gibi görünüyor 2 ile EBXkayıt. Bu varsayımı yapamazsınız ve daha da kötüsü, bölüm 32 bite sığmazsa bölme kolayca bir bölme istisnası üretebilir.
Çözüm için 2'ye bölmenin aslında sadece sağa doğru bir kayma olduğunun farkında olmalısınız.

mov   ebx, [x]
mov   ebp, [x + 4] ; EBP:EBX is x
sar   ebp, 1
rcr   ebx, 1       ; EBP:EBX is x / 2

Bu, bunları EBP:EBXkullanmaya eklemek için diğer hesaplamaları da büyütmeniz gerektiği anlamına gelir :

add   ebx, ...
adc   ebp, ...

Toplama ilişkisel olduğu için e * e kısmını hesaplayarak başlayabilirsiniz . İfadeyi yeniden düzenlemediniz ve sonunda kayıtların etrafında biraz daha dolaşmak zorunda kaldınız. Çok önemli değil, ama benim tarzım daha güzel:

mov   eax, [e]
imul  eax
add   ebx, eax
adc   ebp, edx

Sonra 100 * (a + b) gelir :

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) ' yi sana bırakacağım ...

... ve sonunda son:

sub   ebx, eax
sbb   ebp, edx
mov   [result + 0], ebx 
mov   [result + 4], ebp

gereksiz yere karmaşık hale mi getirdim?

  • Programınızı okumak biraz zordu çünkü farklı işlemler arasına boş satırlar eklemediniz.

  • İlgili kayıt zaten boyutu belirtiyorsa, bir boyut etiketi (bayt, kelime, dword) yazmanıza gerek yoktur. Gelen mov dword [result + 0], eaxdword etiketi gereksiz olduğunu.

  • En iyisi, programdaki yorumları birbirinin üzerine hizalayın.

  • Aşağıdaki gibi yazım hatalarını önlemek için dikkatlice yeniden okuyun:

      mov ecx, edx ; ecx:edx = x / 2 + 100 * (a + b) - 3 / (c + d)
    

    Olmalı ECX:EBX.

  • Bir kareyi hesaplamak için: Sayıyı kasaya yükledikten sonra, aynı kayıtla çarpabilir ve yaptığınız gibi ikinci kez belleğe dönemezsiniz:

      mov   eax, [e]
      imul  eax        ; Don't write "imul dword [e]"