2016-07-11 5 views
1

Je travaille dans l'assemblage NASM 16 bits ayant un problème où mon code ne construira pas. L'erreur se produit sur toutes les lignes MOV ici:Erreur: taille de l'opération non spécifiée - NASm

section .bss 
    x_coord RESB 8 ; [x_coord] is the head, [x_coord+2] is the next cell, etc. 
    y_coord RESB 8 ; Same here 
    pixel_x RESB 2 ; Storage for calculations 
    pixel_y RESB 2 ; Storage for calculations 

    ... 


    MOV [pixel_x], [x_coord] 
    MOV [pixel_y], [y_coord] 
    CALL DrawPixel 

    MOV [pixel_x], [x_coord+2] 
    MOV [pixel_y], [y_coord+2] 
    CALL DrawPixel 

    MOV [pixel_x], [x_coord+4] 
    MOV [pixel_y], [y_coord+4] 
    CALL DrawPixel 

    MOV [pixel_x], [x_coord+6] 
    MOV [pixel_y], [y_coord+6] 
    CALL DrawPixel 

J'ai lu que cela se produit parce que l'assembleur ne sait pas quelle taille les variables sont. J'ai essayé MOV [pixel_x], byte [x_coord] suggéré par un post en ligne, mais cela donne la même erreur. Je veux juste copier les deux premiers octets de x_coord et y_coord en pixel_x/pixel_y, puis les deux suivants, puis les deux suivants, puis les deux suivants. Comment puis-je faire ce travail?

Merci :)

Répondre

4

Le processeur ne dispose pas d'une simple instruction de déplacement de mémoire à la mémoire, de sorte que la bonne chose à faire, si vous voulez déplacer deux octets à la fois, est d'utiliser un inscrire comme intermédiaire:

MOV ax, word [x_coord] 
MOV word [pixel_x], ax 
MOV ax, word [y_coord] 
MOV word [pixel_y], ax 
CALL DrawPixel 

Puisque vos variables sont contiguës en mémoire, vous pourriez aussi être en mesure de le faire:

MOV eax, dword [x_coord] ; move BOTH x_coord AND y_coord into the register 
MOV dword [pixel_x], eax ; populates BOTH pixel_x AND pixel_y 
CALL DrawPixel 

Si vous dessinez seulement quatre pixels, vous pouvez faire les appels les uns après les autres:

MOV eax, dword [x_coord] 
MOV dword [pixel_x], eax 
CALL DrawPixel 
MOV eax, dword [x_coord+2] 
MOV dword [pixel_x], eax 
CALL DrawPixel 
MOV eax, dword [x_coord+4] 
MOV dword [pixel_x], eax 
CALL DrawPixel 
MOV eax, dword [x_coord+6] 
MOV dword [pixel_x], eax 
CALL DrawPixel 

Si vous aviez plus de pixels ne dessiner, vous pourriez envisager d'écrire une boucle.

(A part: Tenir compte également la mise en œuvre DrawPixel d'utiliser des valeurs d'un registre.)

+0

Cela semble parfait, merci! A propos de votre dernier commentaire, j'ai utilisé la mémoire car je ne suis pas sûr à 100% des registres que je suis sûr d'utiliser pour des valeurs temporaires comme celle-ci. Quels sont les meilleurs pour ça? – Nathan

+2

@Nathan: Cela dépend de l'ABI de la fonction. Si vous avez écrit les deux fonctions, vous créez votre propre convention d'appel. Jetez un oeil à quelques ABI/conventions d'appel existantes dans le [wiki tag x86] (http://stackoverflow.com/tags/x86/info). Le __vectorcall 32 bits de Microsoft est probablement un bon point de départ pour le code 16 bits, où les deux premiers arguments entiers sont passés dans les registres. (edx et ecx, IIRC). 32bit SysV (Linux) transmet les arguments sur la pile exclusivement. Même cela serait un meilleur choix que de passer des args dans les globales. ('pousser 'fonctionne avec un opérande de mémoire). –

+0

@Nathan: Si vous utilisez nasm en mode 64 bits, les paramètres de valeurs entières sont passés dans cet ordre: 'rdi',' rsi', 'rdx',' rcx', 'r8',' r9', donc vous seriez susceptible d'écrire votre fonction 'drawPixel' en empaquetant vos deux coordonnées dans les 32 bits de' rdi ​​', 'edi'. Dans une fonction, devrait conserver 'rbp',' rbx', 'r12',' r13', 'r14', et' r15'. Mais il y a beaucoup plus à faire pour utiliser les conventions d'appel (y compris l'alignement, les registres à virgule flottante, les valeurs de retour, etc.), voir http://www.nasm.us/doc/nasmdo11.html et http://x86-64.org /documentation/abi.pdf. –