Question

Je travaille sous visual studio 2005 avec l'ensemble (je suis un débutant) et je veux créer un programme qui calcule la progression arithmétique avec cette règle: A n = 2 * A n-1 + A n-2 mais. Je ne sais vraiment pas comment travailler avec les registres et j'ai besoin juste un exemple de vous de continuer avec mes exercices.

Ceci est mon code:

.386
.MODEL flat,stdcall

.STACK 4096

extern ExitProcess@4:Near

.data                               
arraysize DWORD 10

setarray  DWORD 0 DUP(arraysize)
firstvar  DWORD 1
secondvar DWORD 2

.code                               
_main:                              
mov eax,[firstvar]
mov [setarray+0],eax        
mov eax,[secondvar]
mov [setarray+4],eax

mov ecx, arraysize              ;loop definition
mov ax, 8

Lp:
mov eax,[setarray+ax-4]
add eax,[setarray+ax-4]
add eax,[setarray+ax-8]
mov [setarray+ax],eax

add ax,4;
loop Lp

add ax,4;

    push    0                   ;Black box. Always terminate
    call    ExitProcess@4       ;program with this sequence

    end   _main              ;End of program. Label is the entry point.
Était-ce utile?

La solution

Vous ne pouvez pas utiliser la hache comme registre d'index et EAX comme registre de données en même temps. Pour le code 32bit, bâton à 32 registres de bits, à moins que vous maintenant ce que vous faites. Vous utilisez un mode inadvertance adressage 16 bits, que vous probablement ne voulait pas.

mov ecx, arraysize-1              ;loop definition
mov ebx, 8

Lp:
mov eax,[setarray+ebx-4]
add eax,[setarray+ebx-4]
add eax,[setarray+ebx-8]
mov [setarray+ebx],eax

add ebx,4
dec ecx
jnc Lp

Ne jamais utiliser l'instruction de boucle, même si certains processeurs modernes peuvent exécuter ist rapide (la plupart ne peuvent pas).

Autres conseils

Je suis un débutant en assembleur aussi, mais mon algorithme est un peu différent:


    A   dword   1026 dup (0)          ; declare this in the data segm.

; ...

    mov     esi, offset A         ; point at the results array
    mov     [esi], 1               ; initialize A(0)
    mov     [esi + 4], 2           ;  and A(1)
    xor  ecx, ecx

lp: add esi, 8
mov eax, [esi - 4] ; get A(n-1) add eax, eax ; double it add eax, [esi - 8] ; computes A(n) mov [esi], eax ; and save it inc ecx ; next n cmp ecx, n ; be sure n is a dword, use ; cmp ecx, dword ptr n ; if it isn't jb lp ; loop until ecx < n ; ; now you should have the results in the A array with ; esi pointing to the end of it

Je n'ai pas compilé pour voir si fonctionne bien, mais il se doit ..

A n = 2 * A n-1 + A n-2 est presque la même formule que la suite de Fibonacci, de sorte que vous peut trouver beaucoup de choses utiles en cherchant pour cela. (Par exemple ce q & ). Mais au lieu d'un ajout, nous avons besoin 2a + b, et x86 peuvent le faire dans une instruction LEA.

Vous ne besoin de stocker vos variables de boucle en mémoire, c'est ce que les registres sont pour. Ainsi, au lieu de chaque itération besoin de données de retirer de mémoire (~ 5 cycles de latence pour un aller-retour), il peut simplement utiliser des registres (0 cycles de latence supplémentaire).

Votre tableau peut aller .bss, plutôt que .data, de sorte que vous ne stockez pas les zéros dans votre fichier objet.

arraysize equ 10     ; not DWORD: this is an assemble-time constant, not a value stored in memory

.bss
seq  DWORD 0 DUP(arraysize)   ; I think this is the right MASM syntax?
; NASM equivalent:  seq RESD arraysize

.code
_main:

    mov  edx, 1         ; A[0]
    mov  [seq], edx
    mov  eax, 2         ; A[1]
    mov  [seq+4], eax

    mov  ecx, 8         ; first 8 bytes stored
    ; assume the arraysize is > 2 and even, so no checks here
seqloop:
    lea  edx, [eax*2 + edx]  ;    edx=A[n],   eax=A[n-1]
    mov  [seq + ecx], edx    ; or edx=A[n-1], eax=A[n-2]
    lea  eax, [edx*2 + eax]  
    mov  [seq + ecx + 4], eax
    ; unrolled by two, so we don't need any MOV or XCHG instructions between registers, or any reloading from memory.

    add  ecx, 8             ; +8 bytes
    cmp  ecx, arraysize*4   ; (the *4 happens at assemble time)
    jb   seqloop

    ret

En utilisant l'index de tableau pour les moyens de l'état de la boucle, nous avons utilisé seulement 3 registres au total, et encore ne pas besoin de sauvegarder / restaurer l'un des registres d'appels conservés habituels ESI, EDI, EBX, ou RASE. (Et bien sûr, est restauré ESP de l'appelant, aussi).

Si vous vous souciez de la performance, la boucle est seulement 6 UOP (-domaine de fusion) sur processeurs Intel SNB-famille. Pour plus arraySize, il pourrait fonctionner à un résultat par horloge (une itération par 2 horloges).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top