x / 2 + 100 * (a + b) - 3 / (c + d) + e * e dans l'assemblage

Oct 21 2020

écrire un algorithme pour: x / 2 + 100 * (a + b) - 3 / (c + d) + e * e sachant que: a, c - mot, b, d - octet, e - double mot, 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

ai-je compliqué les choses inutilement?

Réponses

6 SepRoland Oct 22 2020 at 03:52

écrire un algorithme pour: x / 2 + 100 * (a + b) - 3 / (c + d) + e * e

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

Parce que votre plus grand nombre est de 64 bits ( x est un qword), votre résultat final devra également être de 64 bits!

Votre première opération a été de diviser le qword en x par 2. Vous semblez vous attendre à ce que ce résultat tienne dans un seul dword car vous avez déplacé le quotient dans le EBXregistre. Vous ne pouvez pas faire cette hypothèse et pire, la division pourrait facilement produire une exception de division si le quotient ne tient pas dans 32 bits.
Pour la solution, vous devez être conscient que la division par 2 est en fait un simple déplacement vers la droite.

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

Cela signifie que vous devrez également mettre à l'échelle les autres calculs afin de les ajouter à l' EBP:EBXaide de:

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

L'addition étant associative, vous pouvez commencer par calculer la partie e * e . Vous n'avez pas réorganisé l'expression et avez dû déplacer un peu plus les registres à la fin. Pas grand-chose, mais mieux à ma façon:

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

Puis vient 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

Je vous laisse 3 / (c + d) ...

... et enfin la fin sera:

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

ai-je compliqué les choses inutilement?

  • C'était un peu difficile de lire votre programme car vous n'avez pas inséré de lignes vides entre les différentes opérations.

  • Vous n'avez pas besoin d'écrire une balise de taille (octet, mot, dword) si le registre impliqué implique déjà la taille. Dans mov dword [result + 0], eaxla balise dword est redondant.

  • Il vaut mieux aligner les commentaires du programme les uns sur les autres.

  • Relisez attentivement pour éviter les fautes de frappe comme dans:

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

    Devrait être ECX:EBX.

  • Pour calculer un carré: une fois que vous avez chargé le nombre dans le registre, vous pouvez multiplier par ce même registre et ne pas vous tourner vers la mémoire une seconde fois comme vous l'avez fait:

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