2

I'm trying to do the double buffer video in assembler, but in this case i have a problem, i don't know how to solve it , it can't close after a key is pressed. Apparently the problem is in inc di:

(I'm trying to paint all the 320*200 pixel with white color with a buffer)

.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
Daniel Flores
  • 770
  • 3
  • 12
  • 31
  • What do you mean the problem is with `inc di`? Does it work if you comment it out? BTW: It's probably not what's causing your troubles, but you should clear the direction flag (with `cld`) before using `movsb`. – user786653 Jul 03 '11 at 10:47

1 Answers1

2

A few things:

  • Check the return value when you allocate memory (carry is set on error, ax contains the error code, with 8 meaning out of memory) [Note that if you're using a COM file most of the available memory will already be allocated to your program and thus the allocation will fail]
  • You need to clear/set the direction flag before using the string instructions (cld in this case, see e.g. here)
  • After trashing ds in the copying you need to restore it before accessing modovideo (it uses ds implicitly).

With those changes (and some extra to make it work in a COM file) it should work. I used nasm (compile with nasm -f bin -o gfx.com gfx.asm) and DOSBox to test it. Note that the method I employ to allocate memory is probably buggy as it's been a while since I programmed for 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, '$'
user786653
  • 29,780
  • 4
  • 43
  • 53