2015-12-06 79 views
2

我正在將程序從EMU8086環境轉換爲NASM。當裝配NASM給出了這些錯誤:使用ES寄存器給出錯誤

system\kernel.asm:14: error: invalid combination of opcode and operands

system\kernel.asm:20: error: invalid combination of opcode and operands

system\kernel.asm:28: error: invalid combination of opcode and operands

我的代碼是:

jmp start 
    ;============================== 
    ;Draws a horiz and vert line 
    ;============================== 
    startaddr dw 0a000h ;start of video memory 
    colour db 1 
    ;============================== 
    start:  
    mov ah,00  
    mov al,19  
    int 10h   ;switch to 320x200 mode 
    ;============================= 
    horiz:  
    mov es, startaddr  ;put segment address in es *** 1st ERROR HERE! 
    mov di, 32000  ;row 101 (320 * 100)  
    add di, 75   ;column 76  
    mov al,colour   
    mov cx, 160   ;loop counter 
    hplot: 
    mov es:[di],al  ;set pixel to colour *** 2nd ERROR HERE! 
    inc di   ;move to next pixel 
    loop hplot 
    vert:  
    mov di, 16000  ;row 51 (320 * 50)  
    add di, 160   ;column 161  
    mov cx, 100   ;loop counter 
    vplot: 
    mov es:[di],al  ; *** 3rd ERROR HERE! 
    add di, 320   ;mov down a pixel 
    loop vplot 

我已經標有錯誤的行。爲什麼不在NASM中工作?

+1

'MOV ES,[ startaddr]''mov al,[color]'+ missing'hplot:' –

+0

'hplot:'標籤沒有丟失,它只是不與代碼的縮進方式不同,使得它的可讀性大大降低。問題是'loop hplot:'。冒號只在標籤def上,而不是引用。 –

+1

@PeterCordes:這是正確的。我會做的一個觀察是,該程序的第一個版本實際上具有'hplot:'標籤,作爲上述評論的一部分(因此在技術上缺失)。 OP確實轉身解決了這個問題。我猜測德克可能看到了原始代碼。 –

回答

1

沒有處理器指令直接加載esds。你必須加載數據寄存器,然後移動到段寄存器

mov ax,0A000h 
mov es,ax 
3

在NASM你必須用方括號在startaddr檢索值。

寫:

mov es, [startaddr]  ;put segment address in es  

而且NASM希望你寫這些括號內的段重載:

mov [es:di],al  ;set pixel to colour 

一個額外的錯誤NASM不可能檢測到你的是你怎麼想有檢索顏色變量。您還應該使用[]這裏:

mov al, [colour] 
3

替代其他答案

由於0xA000是恆定的,可以將其定義爲這樣的,然後把它作爲一個立即值,而不是內存操作數。爲了使這種方法起作用,您需要將常量放入中間寄存器,然後將其移至段寄存器。


可以定義startaddr爲常數(未存儲器包含段值地址)。您可以使用EQU創建常量(即時值)。既然你不能MOV一個立即值DSESSS直接,您將值轉換成中間

startaddr dw 0a000h ;start of video memory 

startaddr EQU 0a000h ;start of video memory 

:更改此行註冊然後將其移動到段寄存器。所以這個代碼:

mov es, startaddr  ;put segment address in es 

可能是:

mov ax, startaddr 
mov es, ax    ;put segment address in es 

注:如果創建可讀的代碼,並使用上述方法 - 我建議重命名startaddrSTARTADDR。全部大寫標識符的約定向讀者表明它是一個常量(即時值)而不是一個變量。


您所遇到的其他錯誤與EMU8086和NASM之間的語法差異有關。這些行:

mov es:[di],al  ;set pixel to colour 

vplot: 
mov es:[di],al 

需要用方括號內的段被寫入。他們應該是這樣的:

mov [es:di],al  ;set pixel to colour 

vplot: 
mov [es:di],al 

我強烈建議你閱讀NASM documentation有關生成DOS COMEXE程序

+0

@rkhb:當我決定提供答案時,我實際上已經考慮過了。這樣做是非常合法的(因爲您可以將內存操作數移至_ES_)。我決定展示定義視頻存儲器地址常量的典型方法。這兩種方式都有效,但是這個代碼所做的典型成語恕我直言就是我提出的方式。所以兩者都做同樣的事情。我只是避免一個保存常量的內存變量。 –

+0

@rkhb寫了一條評論(現在已經消失),建議'mov es,[startaddr]'。在操作數週圍放置方括號使其成爲內存引用,並可用於OP代碼。我的評論是對此作出的迴應。有人已經提供了使用這種方法的答案,我選擇了一種稍微不同的方法,通常更典型(尤其是如果使用的視頻內存地址不變) –

+0

我看到太遲了,它被@ user3144770回答並刪除了評論。抱歉。 – rkhb