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 (でコンパイルnasm -f bin -o gfx.com gfx.asm) と DOSBox を使用してテストしました。私がメモリを割り当てるために採用した方法は、DOS 用にプログラミングしてからしばらく経っているので、おそらくバグがあることに注意してください。

    組織 0x100

始める:
    ; バックバッファを割り当てる
%if 0
    ; 21h 呼び出しを使用してメモリを割り当てます (EXE ファイルの場合)
    ムーブああ、0x48
    mov bx、64000/16
    整数 0x21
    jcエラー; キャリー・セット・オン・エラー
    mov [vscr_seg], ax
%そうしないと
    ; COMフ​​ァイルは(ほとんど/すべて)利用可能なメモリを取得し、その一部を取得します
    mov bx、単語 [0x0002] ; PSP から最後の段落を取得する
    サブ bx、64000/16 ; バック バッファ用のスペースを確保する
    mov [vscr_seg], bx

    ムーヴアックス、DS
    斧、0x1000を追加します。プログラム開始段落 + 64K (最大 COM ファイル)
    cmp ax、bx ; 合いましたか?
    ジェエラー
%endif
    ; バックバッファをクリア
    ムーブ、[vscr_seg]
    xor ディ、ディ
    斧、斧
    mov cx、32000
    クラッド
    担当者


    ; 前のビデオ モードを取得する
    移動ああ、0x0f
    整数 0x10
    mov [previous_video_mode], al

    ; セットモード 13h (320x200 256色)
    移動斧、0x0013
    整数 0x10

    ; バック バッファの半分を色 15 で塗りつぶす
    ムーブ、[vscr_seg]
    xor ディ、ディ
    移動斧、0x0f0f
    mov cx, 16000
    クラッド
    担当者

    ; そして、一番下の行ですべてのピクセルの色を塗りつぶします
    移動ディ、199 * 320
    mov cx, 255
    xor アル、アル
。塗りつぶし:
    ; 以下の 2 つの命令は、方向フラグがクリアされている場合、stosb と同じです。
    mov [es:di], al
    株式会社ディ

    含む
    ループ .fill

    ; バックバッファから画面へのコピー
    プッシュ ds ; DSのセーブを忘れずに!
    mov ds, [vscr_seg]
    移動斧、0xa000
    移動、斧
    xor ディ、ディ
    xor si, si
    mov cx、32000
    クラッド
    担当者movsw
    ポップDS; ...そして、もう一度復元します

    ; キープレスを待つ
    移動ああ、0x01
    整数 0x21

    ; ビデオモードを復元
    移動ああ、0x00
    mov al, [previous_video_mode]
    整数 0x10

    ; エラーブロックをスキップ
    jmp出口

エラー:
    ; デバッグを容易にするために bx と ax を出力します
    押し斧
    print_hex_word を呼び出す
    ポップアックス
    移動bx、斧
    print_hex_word を呼び出す

    移動ああ、0x09
    mov dx、error_string
    整数 0x21

出口:
    ; 出口
    移動斧、0x4c00
    整数 0x21

; BX に 16 ビット ワードを出力し、AX と DX を破棄します (少なくとも)
print_hex_word:
    移動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 を呼び出す
    ; 改行
    ムーブああ、0x02
    mov dl, 13
    整数 0x21
    mov dl, 10
    整数 0x21
    戻る

print_hex_digit:
    bxを押す
    そしてdl、0x0f
    dl、「0」を追加
    cmp dl、'9'
    jle.print
    dl、'A' - '0' - 10 を追加
.print:
    ムーブああ、0x02
    整数 0x21
    ポップ bx
    戻る


以前のビデオ モード データベース 0
vscr_seg dw 0
error_string db 'エラーが発生しました!', 13, 10, 7, '$'
于 2011-07-03T13:01:56.057 に答える