запись непосредственно в видеопамять

Я слышал, что int 10h, ah = 0Ch работает довольно медленно, и чтобы получить разумную скорость, мне нужно было бы перейти в память и поместить значение в пиксель, который я хочу, я установил свой видеорежим 13h с помощью int 10h. призыв изменить режим видео:

mov ah , 0
mov al , 13h
int 10h

и это процедура, которую я написал, чтобы поместить пиксель в заданные координаты:

drawFaster proc
    ; bp + 2 - row (dx)
    ; bp + 4 - column (cx)
    ; bp + 6 - color
    mov bp , sp
    pushad
    mov ax , 0A000h - presumably the memory address of the screen
    mov es , ax
    mov ax , [bp + 2]
    mov bx , [bp + 4]
    mov cx , 320
    mul cx

    add ax , bx
    mov di , ax
    mov ax , [bp + 6]

    mov [es:di] , al 

    popad
    ret 6
endp

код, вызывающий функцию:

    push bp
    mov ax , 30
    push ax
    mov cx , 50
    push cx
    mov dx , 50
    push dx
    call drawFaster
    pop bp

но по какой-то причине это не дает результатов, я не знаю, неверен ли адрес памяти или что-то еще. Мне нужна ваша помощь. Спасибо!

Странно то, что следующий фрагмент кода работает

mov ax , 0A000H
mov es , ax
mov [es:0] , 30

но следующий фрагмент кода этого не делает:

mov ax , 0A000H
mov bx , 0
mov es , ax
mov [es:bx] , 30

person Guy Sudai    schedule 19.05.2018    source источник
comment
Код для записи в видеопамять мне кажется правильным. Вот несколько вещей, которые нужно проверить: 1) Убедитесь, что параметры переданы правильно. В комментариях упоминаются регистры, а также расположение стека. Если значение пикселя [bp + 6] равно 0, это будет черный цвет. 2) Вы уверены, что цветовая палитра настроена так, как вы хотите? Я предполагаю, что BIOS устанавливает палитру в значения по умолчанию, когда вы устанавливаете режим видео, но я не нашел этому подтверждения.   -  person prl    schedule 20.05.2018
comment
Пара дополнительных комментариев к коду: 1) Он не восстанавливает bp, который в большинстве соглашений о вызовах считается сохраненным. 2) Пожалуйста, не используйте пуша; сохраняйте только те регистры, которые вам нужны, в данном случае bx, di и bp, если вы используете типичное соглашение о вызовах. Вы можете легко избежать использования bx, чтобы избежать его сохранения. Я думаю, что es, наверное, тоже стоит сохранить.   -  person prl    schedule 20.05.2018
comment
Вы уверены насчет этого адреса? См. this, где указано, что это B8000.   -  person David Wohlferd    schedule 20.05.2018
comment
@DavidWohlferd: изменение видеорежима, по-видимому, может изменить базу VGA на 0A0000h. Вывод графики с отображением памяти   -  person Peter Cordes    schedule 20.05.2018
comment
@PeterCordes прав (обычно он прав). Для режима 13h (который указывает OP) правильный адрес a000. Что заставляет меня задуматься, что это за слово на [bp + 6]? И это будет записывать только 1 пиксель за вызов. Действительно ли OP выглядела действительно близко, чтобы убедиться, что это сработало?   -  person David Wohlferd    schedule 20.05.2018
comment
@DavidWohlferd: bp + 6 - это цвет пикселя (8 бит). Я предполагаю, что он использует 320x200, который имеет 8-битный цвет.   -  person Michael Petch    schedule 20.05.2018
comment
@PeterCordes Да, но если он переходит в черный цвет, тогда все будет работать, но все равно результатов не будет.   -  person David Wohlferd    schedule 20.05.2018
comment
Вы можете показать нам код, вызывающий процедуру. Фактически, создание минимально воспроизводимого примера должно помочь людям в этом разобраться. Функция должна работать.   -  person Michael Petch    schedule 20.05.2018
comment
Я почти уверен, что int 10h, ah 13h делает его 256-битным цветом @MichaelPetch   -  person Guy Sudai    schedule 20.05.2018
comment
@prl Я проверил, и они передаются правильно. и я даже попробовал жестко кодировать белый цвет, чтобы убедиться, что цвет не проблема, и в следующий раз я не буду использовать pusha, если мне не нужно, спасибо за советы!   -  person Guy Sudai    schedule 20.05.2018
comment
@prl Я восстанавливаю bp в функциях, которые вызываю drawFaster, с помощью push bp и pop bp   -  person Guy Sudai    schedule 20.05.2018
comment
@MichaelPetch только что отредактировал вопрос. Спасибо за ответ.   -  person Guy Sudai    schedule 20.05.2018
comment
связанные: stackoverflow.com/a/38270279/4271923 не отвечает, почему ваш не работает (потому что должен), но это проверенный рабочий код (для NASM, к сожалению, вы используете устаревший коммерческий TASM), а также он может дать вам представление о том, как эффективно рисовать пиксели напрямую, ваш запутанный пиксель рисования с аргументами, передаваемыми через стек, и pusha/popa похож на 10- В 30 раз медленнее, чем оптимизированная, рисуйте некоторые варианты формы, записывающие несколько пикселей за один раз, с минимальной настройкой на пиксель. Ваш способ будет лишь ненамного быстрее, чем вызов BIOS (хотя и будет быстрее).   -  person Ped7g    schedule 20.05.2018
comment
Другой пример принципа перемещения инициализаций за пределы циклов и минимальной настройки для каждого пикселя приведен здесь: stackoverflow.com/q/50425914/4271923 ... не проверено, мой вариант верен (не удосужился попробовать, настолько уверен, что уверен), но если вы проверите только общее представление о том, что пытается сделать исходный код, и что мой код пытается сделать, вы должны извлечь эту основную идею, как избежать избыточности в коде asm и сделать его действительно быстрее. Скорость кода asm зависит не от использования инструкций asm, а от минимизации объема работы, выполняемой процессором.   -  person Ped7g    schedule 20.05.2018
comment
Кстати, если вы используете турбо-отладчик для отладки этого, имейте в виду, что он не сохраняет содержимое VRAM по умолчанию, поэтому всякий раз, когда вы переключаетесь между графическим режимом и текстовым пользовательским интерфейсом TD, VRAM очищается или повреждается. Задайте параметры - ›Параметры отображения -› Замена отображения на всегда. Затем проверка графического экрана с помощью Alt + F5 должна отображать как минимум пиксели (с поврежденной палитрой каждый раз сбрасывается на значение по умолчанию).   -  person Ped7g    schedule 20.05.2018
comment
@ Ped7g да, я отлаживаю с помощью tasm, я не знал, что дисплей не меняет местами. Спасибо! Я попробую еще раз, только что проверил, и он всегда был включен   -  person Guy Sudai    schedule 20.05.2018
comment
странно то, что если я использую es:0, это работает, но если я использую mov bx , 0, а затем es:bx, это не так. Любые идеи?   -  person Guy Sudai    schedule 20.05.2018
comment
это не имеет смысла, эти два последних примера должны изменить один и тот же фрагмент памяти, если у вас нет какой-то неприятной опечатки (выполняется что-то немного другое, чем в вашем вопросе, где код правильный), проблема, вероятно, в некотором роде ваша оценка работает / не работает или есть какие-то проблемы с вашими инструментами, но все это звучит маловероятно и нелепо. В конечном итоге вы можете попытаться установить es на сегмент данных и в первую очередь указать в данных fakescreen db 320*4 dup (0), чтобы у вас был фальшивый экран размером 320x4, который можно было бы легко проверить с помощью TD, и сначала проверить там код, а затем es = A000 на самом деле.   -  person Ped7g    schedule 20.05.2018
comment
Я имею в виду, что сейчас наступает момент, когда нужно будет увидеть ваш экран / машину, чтобы получить некоторое представление о том, что происходит, извините, но ваше понимание того, как все должно работать и как вы пишете свой код, верно, это не как будто вы понимаете это совершенно неправильно. Где-то должна быть какая-то крошечная деталь. : / У меня закончились идеи.   -  person Ped7g    schedule 20.05.2018
comment
@ Ped7g Я тоже думал, что в этом нет никакого смысла. Но я решил это обходным путем, не уверен, что это хороший ответ, но работает ли он. А пока я доволен. Я могу попробовать изменить это позже.   -  person Guy Sudai    schedule 20.05.2018
comment
Спасибо за вашу помощь, ребята! Я очень благодарен вам за вашу помощь и советы!   -  person Guy Sudai    schedule 20.05.2018
comment
ваш обходной путь - вполне допустимый подход, я тоже иногда использовал ds=A000, когда мне не удавалось записывать пиксели с помощью простого movs/stos или я проделывал с ними дополнительные манипуляции. Это просто не объясняет ваших проблем с другими вариантами. Можете ли вы создать нерабочий пример EXE / COM, загрузить его куда-нибудь и поставить здесь ссылку в комментарии? Я могу попробовать в своем собственном dosbox, чтобы увидеть, сработает ли это для меня.   -  person Ped7g    schedule 20.05.2018
comment
нерабочий пример чего?   -  person Guy Sudai    schedule 20.05.2018
comment
@fdsaddsa mov [es:bx],30 неработающего исполняемого файла ...   -  person Ped7g    schedule 20.05.2018


Ответы (1)


Я нашел обходной путь, но, вероятно, это не лучший способ решить эту проблему вместо использования es (потому что он не работает)

Я изменил адрес сегмента данных на 0A000H,

а затем я меняю пиксель с помощью mov [di] , al, и он работает!

Но если вы пытаетесь это сделать, не забудьте переместить адрес сегмента данных обратно в исходное место.

моя функция в рабочем состоянии, если кому интересно:

drawFaster proc
    ; bp + 2 - row (dx)
    ; bp + 4 - column (cx)
    ; bp + 6 - color
    mov bp , sp ; changing bp to access the stack segment
    ; pushing the values to not lose them in the process of calling the function
    push ax
    push bx
    push cx
    push dx
    mov ax, 0A000h ; 0A000h is the video memory address (for some video modes like 13h)
    mov ds , ax
    mov ax , [bp + 2] ; getting the row ( Y )
    mov bx , [bp + 4] ; getting the column ( X )
    mov cx , 320 ; multiplying the row by 320 to get the offset, and then adding the column
    mul cx

    add ax , bx
    mov di , ax
    mov ax , [bp + 6] ; getting the desired color to paint the pixel in 
    mov [di] , al ; changing the color of the chosen pixel with the desired color
    ; changing the data segment's address back to its original state 
    ; VERY CRUCIAL PLEASE DON'T MISS THIS IF YOU DO IT THE SAME WAY
    mov ax , @data
    mov ds, ax
    ; changing the values back to what they were
    pop dx
    pop cx
    pop bx
    pop ax
    ret 6
endp
person Guy Sudai    schedule 20.05.2018