问题出在第 236 行的 Graphic 子例程内。(子标签 .writePixel 中的第 4、13 和 16 行)。
在此子例程中,我浏览从 280 到 487 列和 368 到 385 行的图形像素。 (像素面积为16x8)。
如果我找到黑色像素,那么我使用
cmovg
指令从垂直条纹的适当区域写入像素,并使用 BIOS 功能 0Ch 中断 int 10h
。
我对 cmovg
指令的操作数有问题。我想将值从数据存储器(全局变量barvy_kontrola)复制到AX寄存器(AH必须是0Ch,AL必须是图形像素的值)。 程序在第一次使用
cmovg
指令时崩溃。这段代码:
pusha
mov si, text_b
call print_string_end2
popa
是测试块(在文本区域(80 x 25)的第23行和35列写入文本)代码如下:
use16
org 0100h
; Return to main entry
Main:
; Set video position and clear the screen automatically
mov ah, 00h ;Invoked with: AH = 00h
mov al, 03h ;text video mode (CGA 80 x 25)
int 10h
; background draw
mov ah, 09h
mov al, 20h ; ASCII char 20h [32(decimal)] is space
xor bh, bh ; set display page 0
mov bl, 1eh ; background of text is blue, foreground is yellow
mov cx, 2000 ; 2000 x copy of space
int 10h
; set cursor position
mov ah, 02h
mov dx, 0624h ; dh = 06h - dl = 24h (row - column)
int 10h
mov si, text_a
call print_string
; set cursor position
add dh, 02h ; rows = rows + 2
sub dl, 0fh ; column = column - 15
push dx ; column index saved
mov ah, 02h
int 10h
mov si, text_b
call print_string
; set cursor position
pop dx ; load index of column
add dh, 01h ; rows = rows + 1
mov ah, 02h
int 10h
push dx ; save cursor of column to next start writing text
mov si, text_c
call print_string
; set cursor position
pop dx ; load index of column
add dh, 02h ; rows = rows + 2
mov ah, 02h
int 10h
push dx ; save cursor of column to next start writing text
mov si, text_d
call print_string
; set cursor position
pop dx ; load index of column
add dh, 02h ; rows = rows + 2
add dl, 06h ; columns = columns + 6
mov ah, 02h
int 10h
mov si, text_e
call print_string
;Save current Video mode (get Video mode and save it)
mov ah, 0fh
int 10h ; returns: current mode in al
push ax ; save
; Read next character to select the choice
mov ah, 01h
int 21h
cmp al, 31h ; 31h is 49 in decimal "1"
jz short choice_1
cmp al, 32h ; 32h is 50 in decimal "2"
jz short choice_2
; other choice exit the program with next code
; wait for key press to exit program
Exit:
mov ah, 07h
int 21h
ret
; choices from the menu
choice_1: ; horizontal color stripes
xor ah, ah ; set graphic mode with resolution (640 x 480)
mov al, 12h
int 10h
;/////////
xor bl, bl ; index pro proch?zen? barev
mov si, barvy
mov ah, 0ch ; Write pixel
mov al, byte [si]
xor cx, cx
xor dx, dx
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
YBack:
int 10h
inc cx
cmp cx, 640
jb short YBack
xor cx, cx
inc dx
pusha ; ulo?en? registr? do z?sobn?ku
mov ax, dx
xor dx, dx
mov bx, 120
div bx
or dx, dx
popa
jnz short YBack
inc bl
cmp bl, 4
je text_continue
inc si
mov al, byte [si]
jmp short YBack
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
choice_2: ; vertical color stripes
xor ah, ah ; set graphic mode with resolution (640 x 480)
mov al, 12h
int 10h
;/////////
xor bl, bl ; index pro procházení barev
mov si, barvy
mov ah, 0ch ; write pixel
mov al, byte [si]
xor cx, cx
xor dx, dx
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
XBack:
int 10h
inc dx
cmp dx, 480
jb short XBack
xor dx, dx
inc cx
pusha ; uložení registrů do zásobníku
mov ax, cx
mov bx, 160
div bx
or dx, dx
popa
jnz short XBack
inc bl
cmp bl, 4
je short text_continue_2
inc si
mov al, byte [si]
jmp short XBack
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
print_string_end2:
mov ah, 02h ; Set cursor
mov dh, 23 ; 23. ??dek
mov dl, 35 ; 35. sloupec
int 10h
mov ah, 02h
.print_char_eE:
mov dl, [si]
inc si
or dl, dl
jz short .DoneP
int 21h
jmp short .print_char_eE
.DoneP:
ret
text_continue_2: ; vykreslení textu "Pres any key to continue" a překreslení pixelů
mov si, text_f
;;;;;;;;;;;;;;; Write text
call print_string_end2
call Graphic
pop ax ; restore video mode
int 10h
jmp Exit ; nastavit skok do Main
;;;;;;;;;;;;;;;
Graphic:
mov cx, 280 ; počáteční sloupec (starting row) (left upper corner if string area)
mov dx, 368 ; počáteční řádek (starting column)+
.ZBack:
mov ah, 0dh ; BIOS funkce čtení pixelu
int 10h
cmp al, 00h
jz short .writePixel
.ContinueZBack:
inc cx
cmp cx, 488
jb short .ZBack
mov cx, 280
inc dx
cmp dx, 386
jb short .ZBack
jmp short .DoneX
.writePixel:
mov di, barvy_kontrola
mov ax, 0c02h ; pro pojištění kdyby nedopadla žádná podmínka (defaultní nastavení pixelu)
cmp cx, 479
cmovg ax, [di] ;[barvy_kontrola]
pusha
mov si, text_b
call print_string_end2
popa
add di, 02h
cmp cx, 319
cmovg ax, [di]
add di, 02h
cmp cx, 159
cmovg ax, [di]
int 10h ; BIOS funkce pro zápis pixelu
jmp short .ContinueZBack
.DoneX:
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
text_continue: ; print text "Pres any key to continue"
pop ax ; restore video mode
int 10h
mov si, text_f
call print_string_end
jmp Exit ; místo Exit nastavit do Main
print_string:
mov ah, 09h
mov bl, 1eh ; background is blue, foreground is yellow
mov cx, 01h
.print_char:
lodsb
or al, al
jz short .done
int 10h
push ax
mov ah, 02h ; Bios function to set cursor position
inc dl ; move cursor
int 10h
pop ax
jmp short .print_char
.done:
ret
print_string_end:
mov ah, 02h ; Set cursor
mov dh, 23 ; 23. ??dek
mov dl, 35 ; 35. sloupec
int 10h
.print_string_e:
mov ah, 02h
.print_char_e:
mov dl, [si]
inc si
or dl, dl
jz short .Continue
int 21h
jmp short .print_char_e
.Continue:
mov si, barvy
lea di, [barvy + 3]
xor bl, bl
;Read pixel and write new pixel
.ContinueColor:
mov dx, 368 ; row
mov cx, 280
mov ah, 0dh ; function of read graphic pixel
.Gback:
int 10h
cmp al, [si] ; [si] <= mov si, barvy
jnz short .GbackRow
push ax
mov ah, 0ch
mov al, [di] ; [di] <= lea di, [barvy + 3]
int 10h
pop ax
jmp short .GbackRow
.GbackRow:
inc cx
cmp cx, 488
jb short .Gback
mov cx, 280 ; start column
inc dx
cmp dx, 386
jb short .Gback
lea si, [barvy + 4]
mov di, barvy
inc bl
cmp bl, 02h
jb short .ContinueColor
ret
; Exit program
Return:
ret
text_a: db "MENU", 00h
text_b: db "1 - HORIZONTAL STRIPES", 00h
text_c: db "2 - VERTICAL STRIPES", 00h
text_d: db "Q - QUIT", 00h
text_e: db "ENTER CHOICE:", 00h
text_f: db "Press any key to continue", 00h
barvy: db 00h, 05h, 0eh, 01h, 0fh ; color Black, Magenta, Yellow, Dark blue; White
barvy_kontrola: db 0ch, 01h, 0ch, 0eh, 0ch, 05h
我想使用子例程Graphic(代码下方)在图形模式 12h 下重绘文本区域的背景。文本区域为“1 - HORIZONTAL STRIPESnue”,以适合图形垂直条纹的图形像素。
我使用FASM汇编器。
第一次使用首先确保您有权访问此特定说明。您可以通过检查
cmovg
指令时程序崩溃。
cpuid
指令的结果来了解其可用性:
mov eax, 1
cpuid ; -> EAX EBX ECX EDX
bt edx, 15
jnc NotSupported
如果在这里设置了进位标志,那么使用cmovg
(和朋友)将会是安全的。如果
cmovg
确实有效,那么barvy_kontrola 数组中就会出现一个重要错误。
barvy_kontrola: db 0ch, 01h, 0ch, 0eh, 0ch, 05h
由于 x86 是小端架构,因此从该数组加载 AX 会将 BIOS 函数编号放入 AL 寄存器中,而不是放入其所属的 AH 寄存器中。不过颜色是 AL 的。您可以写:
barvy_kontrola: dw 0C01h, 0C0Eh, 0C05h
或
barvy_kontrola: db 01h, 0Ch, 0Eh, 0Ch, 05h, 0Ch