2

In x86 asm, what is the right, fast way to copy from VRAM to an array variable in VGA mode 13? I can copy to VRAM no issue using movsb, but copying from VRAM using movsb produces weird results, or can crash my program.

I have a test program to create a line in VRAM, copy that line from VRAM to a variable, then copy that variable to another location in VRAM. The program doesn't work as it is -- strangely changing count dw 320 to count equ 320 makes it work. Any idea what I'm doing wrong? I don't believe changing the count variable is a viable fix.

; assemble with A86
jmp main

vdata db 320 dup 14
vdata_backup db 320 dup 0

video_memory equ 0a000h
count dw 320

wait_for_key:
        mov ax, 0h
        int 016h
        ret

main:
        ; set up mode 13
        mov ax, 013h
        int 10h

        ; copy some data to VRAM
        ; create a line on the screen
        mov si, offset vdata
        mov es, video_memory
        mov di, 640
        mov cx, count
        rep movsb

        ; copy from VRAM to vdata_backup
        push ds
        mov ds, video_memory
        mov si, 640
        mov es, code
        mov di, offset vdata_backup
        mov cx, count
        rep movsb
        pop ds

        ; copy vdata_backup to different part of VRAM
        ; create a new line on the screen
        mov si, offset vdata_backup
        mov es, video_memory
        mov di, 3200
        mov cx, count
        rep movsb

        call wait_for_key

        ; set back to text mode
        mov ah, 0
        mov al, 3
        int 10h

        ; exit to dos
        mov ah, 4ch
        int 21h
Michael Petch
  • 46,082
  • 8
  • 107
  • 198
Alabaster
  • 23
  • 4
  • BTW, back on real 80386 and 80486 you did want to avoid reading VRAM quite a lot, already the *write* to VRAM was on many VGA cards 5-10x slower than write into regular RAM (on cards with good caching it was like 1.5-3x slower), but *read* was on cards with good caching even 3-5x slower than write, as nobody was expecting to do many reads. Graphical effects requiring background data were often running faster when you produced the final image in regular memory and copied to VRAM only result, even in cases where the current VRAM buffer may be handy like blur effect. – Ped7g Sep 09 '19 at 15:21

1 Answers1

3

In the section of code copy from VRAM to vdata_backup you do:

push ds
mov ds, video_memory 
[snip]
mov cx, count

You have altered DS so it points to the video graphics segment A000. That is not the segment where count resides. mov cx, count implicitly uses the DS segment and is similar to doing mov cx, [ds:count]. You have retrieved the count from the wrong place in memory. The simple fix is to retrieve count before you modify DS. The code could look like:

push ds
mov cx, count
mov ds, video_memory 
[snip]
Michael Petch
  • 46,082
  • 8
  • 107
  • 198
  • 1
    Excellent, this worked right away. Thank you. This helped me further understand how movsb works. Maybe what I'm doing is odd, but I hadn't yet found text on the side effects of updating the ds register. – Alabaster Sep 15 '19 at 19:20