Копировать из VRAM с помощью movsb?

В x86 asm, каков правильный и быстрый способ копирования из VRAM в переменную массива в режиме VGA 13? Я могу без проблем скопировать в VRAM с помощью movsb, но копирование из VRAM с помощью movsb приводит к странным результатам или может сбой моей программы.

У меня есть тестовая программа для создания строки в VRAM, копирования этой строки из VRAM в переменную, а затем копирования этой переменной в другое место в VRAM. Программа не работает сама по себе — странным образом изменение count dw 320 на count equ 320 заставляет ее работать. Любая идея, что я делаю неправильно? Я не думаю, что изменение переменной count является жизнеспособным решением.

; 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

person Rugtastic    schedule 08.09.2019    source источник
comment
Кстати, на реальных 80386 и 80486 вы действительно хотели избежать большого количества чтения VRAM, уже сейчас запись в VRAM была на многих VGA-картах в 5-10 раз медленнее, чем запись в обычную RAM (на картах с хорошим кэширование было примерно в 1,5-3 раза медленнее), но чтение было на картах с хорошим кэшированием даже в 3-5 раз медленнее, чем запись, так как никто не ожидал, что будет много операций чтения. Графические эффекты, требующие фоновых данных, часто работали быстрее, когда вы создавали финальное изображение в обычной памяти и копировали результат только в VRAM, даже в тех случаях, когда текущий буфер VRAM может быть удобен, например эффект размытия.   -  person Ped7g    schedule 09.09.2019


Ответы (1)


В разделе кода копировать из VRAM в vdata_backup вы делаете:

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

Вы изменили DS, чтобы он указывал на сегмент видеографики A000. Это не тот сегмент, где находится count. mov cx, count неявно использует сегмент DS и аналогично выполнению mov cx, [ds:count]. Вы извлекли count из неправильного места в памяти. Простое решение состоит в том, чтобы получить count перед изменением DS. Код может выглядеть так:

push ds
mov cx, count
mov ds, video_memory 
[snip]
person Michael Petch    schedule 08.09.2019
comment
Отлично, это сработало сразу. Спасибо. Это помогло мне лучше понять, как работает movsb. Может быть, то, что я делаю, странно, но я еще не нашел текста о побочных эффектах обновления регистра ds. - person Rugtastic; 15.09.2019