2016-07-11 25 views
1

Ich arbeite in 16-Bit-NASM-Assembly mit einem Problem, wo mein Code nicht erstellt wird. Der Fehler tritt auf allen MOV Linien hier:Fehler: Betriebsgröße nicht angegeben - 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 

ich gelesen habe, dass dies geschieht, weil der Assembler nicht weiß, welche Größe die Variablen. Ich habe versucht MOV [pixel_x], byte [x_coord] von einigen Online-Post vorgeschlagen, aber das gibt den gleichen Fehler. Ich möchte nur die ersten zwei Bytes von x_coord und y_coord in pixel_x/pixel_y kopieren, dann die nächsten zwei, dann die nächsten zwei, dann die nächsten zwei. Wie kann ich das schaffen?

Thanks :)

Antwort

4

Der Prozessor, keinen einfachen Speicher-zu-Speicher-Bewegungsbefehl hat so das Richtige zu tun, wenn Sie zwei Bytes auf einmal verschieben mögen, eine zu verwenden ist registrieren als Vermittler:

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

da Ihre Variablen angrenzen im Speicher, können Sie auch in der Lage sein, dies zu tun:

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 

Wenn Sie nur vier Pixel zeichnen, können Sie die Anrufe nacheinander tun:

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 

Wenn Sie mehr Pixel zeichne haben, könnten Sie eine Schleife zu schreiben.

(Abgesehen: Sehen Sie auch DrawPixel Umsetzung Werte aus einem Register zu verwenden.)

+0

Das sieht perfekt, danke! Über deinen letzten Kommentar habe ich Speicher verwendet, weil ich mir nicht 100% ig sicher bin, welche Register ich für Temperaturwerte wie diese sicher verwenden kann. Welches sind die besten dafür? – Nathan

+2

@Nathan: Es hängt von der ABI der Funktion ab. Wenn Sie beide Funktionen geschrieben haben, können Sie Ihre eigene Aufrufkonvention erstellen. Sehen Sie sich einige existierende ABIs/Aufrufkonventionen im [x86 tag wiki] (http://stackoverflow.com/tags/x86/info) an. Der 32-Bit-__vectorcall von Microsoft ist wahrscheinlich ein guter Ausgangspunkt für 16-Bit-Code, wo die ersten zwei ganzzahligen Argumente in Registern übergeben werden. (edx und ecx, IIRC). 32bit SysV (Linux) übergibt ausschließlich Args auf dem Stack. Selbst das wäre eine bessere Wahl als das Übergeben von Argumenten in Globalen. ('push' arbeitet mit einem Speicheroperanden). –

+0

@Nathan: Wenn Sie nasm im 64-Bit-Modus verwenden, werden die ganzzahligen Parameter in dieser Reihenfolge übergeben: 'rdi',' rsi', 'rdx',' rcx', 'r8',' r9', so Sie würden wahrscheinlich Ihre 'drawPixel'-Funktion schreiben, indem Sie Ihre zwei Koordinaten in die niederwertigen 32 Bits von' rdi', nämlich 'edi', packen. Innerhalb einer Funktion sollten "rbp", "rbx", "r12", "r13", "r14" und "r15" beibehalten werden. Aber es gibt viel mehr Funktionen zum Aufrufen von Konventionen (einschließlich Ausrichtung, Fließkomma-Register, Rückgabewerte usw.), siehe http://www.nasm.us/doc/nasmdo11.html und http://x86-64.org /dokumentation/abi.pdf. –