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
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]