2016-09-21 1 views
0

Je suis assez nouveau à l'Assemblée, et j'ai un hardtime traiter nombre négatifdans l'assemblage avec multiplication nombre négatif et le résultat

#include <stdio.h> 
void main() { 
    short int mat1[] = {-1,-2, 4,5, 4,-2}; // first array 
    short int mat2[] = {2,0,0,0, 0,2,0,0}; // second array 
    int mat3[1024]; // result array 

    __asm { 
     MOV AX, mat1[0] ; mat1[0]:= -1 
     MOV BX, mat2[0] ; mat2[0]:= 2 
     ; my problem is how i can do this 
     ; mat3[0] = mat1[0] * mat2[0] ; 
     ; (operation result -> mat3[0] = -2) 
    } 
} 

de P.S. Ceci est pour mes devoirs merci à l'avance


Nouvelle Question:

Après tente une opération de montage:

MOV AX, mat1[ECX] ; eax is 0 and mat1[ecx] is -1 

mais après cette opération comment se AX est réglé sur 65535 et non à -1? Comment puis-je effectuer une multiplication correcte si le registre AX n'est pas correct? Je confonds tout à fait la façon de traiter complément de 2.


Je suis une autre question. actuellement j'ai ce code où je me déplace IMUL résultat à tableau.

MOV WORD PTR mat3[ECX*4]+0, AX 
    MOV WORD PTR mat3[ECX*4]+2, DX 

Ma question est comment puis-je ajouter le résultat IMUL à la valeur Array [idx] actuelle?

avec ceci où mat3 [indice actuel] = 0, l'opération est correcte. mais quand par exemple mat3 [index actuel] = -2, j'ai un nombre différent de ce que je m'attends à obtenir.

ADD WORD PTR mat3[ECX*4]+0, AX 
    ADD WORD PTR mat3[ECX*4]+2, DX 

Je vous remercie d'avance pour votre aide

+0

Pas besoin de répondre. J'ai déjà compris. – whebz

+0

Voir aussi [ma réponse ici sur la multiplication des nombres 16 bits et la production d'un résultat 32 bits ('int') (http://stackoverflow.com/questions/39581293/invalid-instruction-operands-on-mov-ah -word-variable-et-using-imul-on-16-bi/39582213 # 39582213). –

Répondre

3

Avec l'architecture 8086, il y a deux instructions pour multiplier deux nombres, mais différents arguments peuvent être utilisés:

Val8 DB 12  ; 8-bit variable 
Val16 DW 12345 ; 16-bt variable 

MUL BL   ; Unsigned multiply of 8-bit register 
MUL [Val8]  ; Unsigned multiply of 8-bit memory location 
MUL BX   ; Unsigned multiply of 16-bit register 
MUL [Val16] ; Unsigned multiply of 16-bit memory location 

IMUL BL   ; Signed multiply of 8-bit register 
IMUL [Val8]  ; Signed multiply of 8-bit memory location 
IMUL BX   ; Signed multiply of 16-bit register 
IMUL [Val16] ; Signed multiply of 16-bit memory location 

Mais .. .si elle multiplie deux variables, où est la deuxième variable? La réponse est que la deuxième variable est toujoursAL pour les multiplications de 8 bits, et toujoursAX pour les multiplications de 16 bits.

  • Le résultat d'une multiplication 8 bits peut être jusqu'à 16 bits, il est donc toujours stockée dans AX.
  • Le résultat d'une multiplication de 16 bits peut aller jusqu'à 32 bits! Oh oh! Le 8086 n'a pas de registres 32 bits! Où stocke-t-il le résultat? Au DX:AX. C'est-à-dire, il stocke les 16 bits élevés dans DX, et les 16 bits faibles dans AX.

Pour votre code, au lieu de se déplacer dans mat2[0]BX, vous pouvez simplement IMUL directement de la mémoire - et oui, vous devez utiliser IMUL puisque vous voulez un signé se multiplient. Une fois que vous avez le résultat du IMUL, vous devez stocker le résultat dans mat3[0].Puisque vous ne pouvez pas déplacer DX:AX avec une instruction, vous en avez besoin de deux. Je ne sais pas qui assembleur que vous utilisez, mais généralement la syntaxe serait quelque chose comme ceci:

MOV WORD PTR mat3[0]+0, AX 
MOV WORD PTR mat3[0]+2, DX 

Regardez le soin ci-dessus! mat3[0] est un int de 32 bits, donc vous ne pouvez pas y déplacer un registre de 16 bits. Vous devez indiquer à l'assembleur de le traiter comme WORD (16 bits) en premier. Et pour stocker le haut 16 bits qui sont en DX, vous devez les mettre aprèsAX en mémoire, ainsi le +2. (Le +0 dans la ligne avant est juste pour la symétrie).

Ne pas oublier: le 8086 stocke ses valeurs multi-octets avec les octets les moins significatifs d'abord. Cela signifie que vous devez stocker les deux parties du résultat comme je l'ai montré ci-dessus.

+0

L'OP utilise clairement le code 32 bits de C++, et ne se limite pas à fonctionner sur 8086. La forme à deux opérandes de imul est très pratique. En outre, l'assembleur utilisé est celui intégré à MSVC++. Si je comprends bien, c'est un peu comme MASM. –

+1

@PeterCordes Quand j'ai vu la question pour la première fois, il y avait: une étiquette 8086; seulement des instructions x86; et seulement le code C++ original. Ces dernières modifications ... changent les choses. À vous! –

+1

@Macmade D'oh! Je ne peux pas croire que j'ai souffert de l'erreur copier/coller comme ça! Je vous remercie. –