2

我正在尝试在汇编程序中制作双缓冲视频,但在这种情况下我有一个问题,我不知道如何解决它,按下一个键后它无法关闭。显然问题出在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
4

1 回答 1

2

一些东西:

  • 分配内存时检查返回值(进位设置错误,ax包含错误代码,8表示内存不足)[注意,如果您使用的是COM文件,大部分可用内存将已经分配给您的程序因此分配将失败]
  • 您需要在使用字符串指令之前清除/设置方向标志(cld在这种情况下,请参见此处的示例)
  • ds复制中删除后,您需要在访问之前恢复它modovideo(它ds隐式使用)。

通过这些更改(以及使其在 COM 文件中工作的一些额外内容),它应该可以工作。我使用 nasm (compile with nasm -f bin -o gfx.com gfx.asm) 和 DOSBox 来测试它。请注意,我用来分配内存的方法可能是错误的,因为我已经有一段时间没有为 DOS 编程了。

    组织 0x100

开始:
    ; 分配后台缓冲区
% 如果 0
    ; 使用 21h 调用分配内存(对于 EXE 文件)
    移动啊,0x48
    mov bx, 64000/16
    整数 0x21
    jc错误;进行错误设置
    mov [vscr_seg], 斧头
%别的
    ; COM 文件获得(大部分/全部)可用内存,获取其中一些
    mov bx, 字 [0x0002] ; 从 PSP 获取最后一段
    子 bx,64000/16;为后台缓冲区腾出空间
    mov [vscr_seg], bx

    mov ax, ds
    添加斧头,0x1000;程序开始段 + 64K(COM 文件的最大值)
    cmp 斧头, bx ; 合适吗?
    错误
%万一
    ; 清除后台缓冲区
    移动,[vscr_seg]
    异或迪
    xor 斧头,斧头
    mov cx, 32000
    分类
    代表存储


    ; 获取上一个视频模式
    mov 啊,0x0f
    整数 0x10
    mov [previous_video_mode], 人

    ; 设置模式 13h(320x200 256 色)
    移动斧头,0x0013
    整数 0x10

    ; 用颜色 15 填充一半的后台缓冲区
    移动,[vscr_seg]
    异或迪
    移动斧头,0x0f0f
    mov cx, 16000
    分类
    代表存储

    ; 并在底行填写所有像素颜色
    mov di, 199 * 320
    mov cx, 255
    xor al, 艾尔
。充满:
    ; 以下两条指令在方向标志清零时等于 stosb
    mov [es:di], 人
    公司二

    包括
    循环 .fill

    ; 从后台缓冲区复制到屏幕
    推 ds ; 记得保存DS!
    mov ds, [vscr_seg]
    移动斧头,0xa000
    移动,斧头
    异或迪
    xor si, si
    mov cx, 32000
    分类
    代表 movsw
    流行音乐;...并再次恢复它

    ; 等待按键
    mov 啊, 0x01
    整数 0x21

    ; 恢复视频模式
    移动啊,0x00
    mov al, [previous_video_mode]
    整数 0x10

    ; 跳过错误块
    退出

错误:
    ; 打印bx和ax,方便调试
    推斧
    调用 print_hex_word
    流行斧
    mov bx, ax
    调用 print_hex_word

    mov 啊,0x09
    mov dx, error_string
    整数 0x21

出口:
    ; 出口
    移动斧头,0x4c00
    整数 0x21

; 在 BX 中打印 16 位字,丢弃 AX 和 DX(至少)
print_hex_word:
    mov dx, bx
    shr dx, 12
    调用 print_hex_digit
    mov dl, bh
    调用 print_hex_digit
    mov dl, bl
    shr dl, 4
    调用 print_hex_digit
    mov dl, bl
    调用 print_hex_digit
    ; 新队
    mov 啊,0x02
    电影 dl, 13
    整数 0x21
    mov dl, 10
    整数 0x21
    ret

print_hex_digit:
    推bx
    和 dl, 0x0f
    添加dl,'0'
    cmp dl, '9'
    jle .print
    添加 dl, 'A' - '0' - 10
。打印:
    mov 啊,0x02
    整数 0x21
    流行音乐
    ret


previous_video_mode 数据库 0
vscr_seg dw 0
error_string db '发生错误!', 13, 10, 7, '$'
于 2011-07-03T13:01:56.057 回答