我正在尝试在汇编程序中执行双缓冲视频,但在这种情况下我有一个问题,我不知道如何解决它,按下一个键后它无法关闭。显然问题出在 inc di :
(我试图用缓冲区绘制所有320 * 200像素的白色)
.model small
.386
.stack 400h
.data
modovideo db ?
vram dw 0
xVal dw ?
yVal dw ?
.code
main proc
mov ax,@data
mov ds,ax
mov ah,0fh
int 10h
mov modovideo,al
mov ah,0
mov al,13h
int 10h
; Segmento de memoria =====================================
mov ah,48h
mov bx,4000 ; 64000/16
int 21h
mov vram,ax
; Escribir en el segmento de memoria =======================================
mov es,vram
;offset = 320*y + x
;mov xVal,160
;mov yVal,100
;mov ax,320
;mul yVal
;add ax,xVal
mov di,0
mov al,7
mov cx,640
paso1:
mov es:[di],al
inc di ; <-----------
loop paso1
; Volcar sobre pantalla ======================================================
mov ds,vram
xor si,si
mov dx,0A000h
mov es,dx
xor di,di
mov cx,64000
rep movsb
mov ah,1
int 21h
salir:
mov al,modovideo
mov ah,0
int 10h
mov ah,4ch
int 21h
main endp
答案 0 :(得分:2)
一些事情:
ax
包含错误代码,8表示内存不足)[注意,如果您使用的是COM文件,大部分可用内存已经分配给你的程序,因此分配将失败] cld
,请参阅例如here)ds
后,您需要在访问modovideo
之前将其恢复(隐式使用ds
)。通过这些更改(以及一些额外的使其在COM文件中工作),它应该工作。我使用nasm(用nasm -f bin -o gfx.com gfx.asm
编译)和DOSBox来测试它。请注意,我用来分配内存的方法很可能因为我为DOS编程已经有一段时间了。
org 0x100 start: ; Allocate back buffer %if 0 ; Use 21h call to allocate memory (for EXE files) mov ah, 0x48 mov bx, 64000/16 int 0x21 jc error ; carry set on error mov [vscr_seg], ax %else ; COM files get (most/all) available memory, grab some of it mov bx, word [0x0002] ; Get last paragraph from PSP sub bx, 64000/16 ; Make room for back buffer mov [vscr_seg], bx mov ax, ds add ax, 0x1000 ; Program start paragraph + 64K (max of COM file) cmp ax, bx ; Did it fit? jae error %endif ; Clear back buffer mov es, [vscr_seg] xor di, di xor ax, ax mov cx, 32000 cld rep stosw ; Get previous video mode mov ah, 0x0f int 0x10 mov [previous_video_mode], al ; Set mode 13h (320x200 256 colors) mov ax, 0x0013 int 0x10 ; Fill half the back buffer with color 15 mov es, [vscr_seg] xor di, di mov ax, 0x0f0f mov cx, 16000 cld rep stosw ; And fill in all pixel colors at bottom row mov di, 199 * 320 mov cx, 255 xor al, al .fill: ; the below two instructions are equal to stosb when the direction flag is cleared mov [es:di], al inc di inc al loop .fill ; Copy from back buffer to the screen push ds ; Remember to save DS! mov ds, [vscr_seg] mov ax, 0xa000 mov es, ax xor di, di xor si, si mov cx, 32000 cld rep movsw pop ds ; ... And restore it again ; Wait for keypress mov ah, 0x01 int 0x21 ; Restore video mode mov ah, 0x00 mov al, [previous_video_mode] int 0x10 ; Skip error block jmp exit error: ; Print bx and ax to facilitate debugging push ax call print_hex_word pop ax mov bx, ax call print_hex_word mov ah, 0x09 mov dx, error_string int 0x21 exit: ; Exit mov ax, 0x4c00 int 0x21 ; Print 16-bit word in BX, trashes AX and DX (at least) print_hex_word: mov dx, bx shr dx, 12 call print_hex_digit mov dl, bh call print_hex_digit mov dl, bl shr dl, 4 call print_hex_digit mov dl, bl call print_hex_digit ; New line mov ah, 0x02 mov dl, 13 int 0x21 mov dl, 10 int 0x21 ret print_hex_digit: push bx and dl, 0x0f add dl, '0' cmp dl, '9' jle .print add dl, 'A' - '0' - 10 .print: mov ah, 0x02 int 0x21 pop bx ret previous_video_mode db 0 vscr_seg dw 0 error_string db 'Error occurred!', 13, 10, 7, '$'