如何使用cmovg指令从内存数据设置寄存器

问题描述 投票:0回答:1

问题出在 Graphic 子例程的第 236 行。(子标签 .writePixel 中的第 4、13 和 16 行) 在此子例程中,我浏览从 280 到 487 列和 368 到 385 行的图形像素。 (像素面积为16x8) 如果我找到黑色像素,那么我使用 cmovg 指令从垂直条纹的适当区域写入像素,并使用 BIOS 功能 0Ch 中断 INT 10h。

我对 cmovg 指令的操作数有问题。我想将值从数据存储器(全局变量“barvy_kontrola”)复制到 AX 寄存器(AH 必须是 OCh,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 汇编器。

assembly dos fasm operands conditional-move
1个回答
0
投票

第一次使用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
© www.soinside.com 2019 - 2024. All rights reserved.