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

Oct 21 2020

scrivi un algoritmo per: x / 2 + 100 * (a + b) - 3 / (c + d) + e * e sapendo che: 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

l'ho reso inutilmente complicato?

Risposte

6 SepRoland Oct 22 2020 at 03:52

scrivi un algoritmo per: x / 2 + 100 * (a + b) - 3 / (c + d) + e * e

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

Poiché il tuo numero più grande è 64 bit ( x è una qword), anche il tuo risultato finale dovrà essere 64 bit!

La tua prima operazione è stata quella di dividere la qword in x per 2. Sembri aspettarti che questo risultato si adatti a una singola dword perché hai spostato il quoziente nel EBXregistro. Non puoi fare questa ipotesi e, peggio ancora, la divisione potrebbe facilmente produrre un'eccezione di divisione se il quoziente non si adatta a 32 bit.
Per la soluzione dovresti essere consapevole che la divisione per 2 è in realtà semplicemente uno spostamento a destra.

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

Ciò significa che dovrai ridimensionare anche gli altri calcoli per aggiungerli EBP:EBXall'utilizzo:

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

Poiché l'aggiunta è associativa, puoi iniziare calcolando la parte e * e . Non hai riorganizzato l'espressione e alla fine hai dovuto spostare ancora un po 'i registri. Non è un grosso problema, ma è più carino a modo mio:

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

Poi arriva 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

Lascio 3 / (c + d) a te ...

... e finalmente la fine sarà:

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

l'ho reso inutilmente complicato?

  • È stato un po 'difficile leggere il tuo programma perché non hai inserito alcune righe vuote tra le diverse operazioni.

  • Non è necessario scrivere un tag di dimensione (byte, parola, parola chiave) se il registro coinvolto già implica la dimensione. Nel mov dword [result + 0], eaxtag dword è ridondante.

  • È meglio che i commenti nel programma siano allineati uno sopra l'altro.

  • Rileggi attentamente per evitare errori di battitura come in:

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

    Dovrebbe essere ECX:EBX.

  • Per calcolare un quadrato: una volta caricato il numero nel registro, puoi moltiplicarlo per quello stesso registro e non tornare alla memoria una seconda volta come hai fatto:

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