Assembly 为什么我在vga图形模式下写入字符后0小时才读取?

Assembly 为什么我在vga图形模式下写入字符后0小时才读取?,assembly,x86,x86-16,osdev,real-mode,Assembly,X86,X86 16,Osdev,Real Mode,在实模式(或虚拟8086)中,当我切换到vga图形模式(00DH,00EH,012H)并使用BIOS功能显示字符(int 00AH,int 00EH)时,除了一堆零之外,无法从0xA0000读取任何内容。这个角色确实显示在屏幕上,但从记忆中看不清楚。文本模式(1H,3H,…)下一切正常 format binary use16 org 07C00H _TELETYPE_GRAPHIC_40x25 = 00DH _TELETYPE_GRAPHIC_80x25 = 00EH _TELETYPE_GR

在实模式(或虚拟8086)中,当我切换到vga图形模式(00DH,00EH,012H)并使用BIOS功能显示字符(int 00AH,int 00EH)时,除了一堆零之外,无法从0xA0000读取任何内容。这个角色确实显示在屏幕上,但从记忆中看不清楚。文本模式(1H,3H,…)下一切正常

format binary
use16
org 07C00H

_TELETYPE_GRAPHIC_40x25 = 00DH
_TELETYPE_GRAPHIC_80x25 = 00EH
_TELETYPE_GRAPHIC_80x30 = 012H

cli

mov ax, _TELETYPE_GRAPHIC_80x30
int 010H

mov ax, 00E41H
mov bx, 2H
int 010H

mov bx, 0A000H
mov es, bx
xor di, di
xor ax, ax
mov cx, 04000H
cld
rep scasb
jz _always
hlt
jmp $-1H
_always:
; ...

我尝试在64位Windows上的DOSBox中使用TurboDebugger以图形模式13h(320*200px)读取videomemory,它按预期工作:
REPE SCASB
停止,DI=0143h,加载值
MOV-AL[ES:DI-1]
was2
ES:0(140h字节)处的第一个像素行全部为0(黑色),第二行从ES:0140h开始,有两个黑色像素(0字节),然后是值为
AL=2(蓝色)的字节,这是大写字母A字形的尖端

但是,由于调试器和DOSBox仿真的不完善,无法使用Alt-F5在TurboDebugger用户屏幕和CPU窗口之间切换来检查视频内存。 平面图形模式0Dh、0Eh、12h的情况更为复杂。VGA将所有四个内存平面(页面)映射到同一线性地址A0000h,您必须首先通过直接输出到CRT端口来选择页面(请参阅@fuz first comment中的链接)。 您可能希望从videoram加载非零字节,并使用
int10h
而不是
hlt
打印它,以确保它在那里

我记得大约30年前,我是如何调试图形程序的,两台DOS计算机通过串口连接,使用Borland TD.EXE和TDREMOTE.EXE。我能够单步执行写入EGA/VGA CRT寄存器的指令,并观看效果,而无需在调试器窗口和用户屏幕之间切换


我不确定你想要实现什么,但在非模拟DOS中,图形模式13h你可能会成功。

我尝试在64位窗口上的DOSBox中使用TurboDebugger在图形模式13h(320*200px)下读取视频内存,它按预期工作:
REPE SCASB
停止,DI=0143h,加载值
MOV-AL[ES:DI-1]
was2
ES:0(140h字节)处的第一个像素行全部为0(黑色),第二行从ES:0140h开始,有两个黑色像素(0字节),然后是值为
AL=2(蓝色)的字节,这是大写字母A字形的尖端

但是,由于调试器和DOSBox仿真的不完善,无法使用Alt-F5在TurboDebugger用户屏幕和CPU窗口之间切换来检查视频内存。 平面图形模式0Dh、0Eh、12h的情况更为复杂。VGA将所有四个内存平面(页面)映射到同一线性地址A0000h,您必须首先通过直接输出到CRT端口来选择页面(请参阅@fuz first comment中的链接)。 您可能希望从videoram加载非零字节,并使用
int10h
而不是
hlt
打印它,以确保它在那里

我记得大约30年前,我是如何调试图形程序的,两台DOS计算机通过串口连接,使用Borland TD.EXE和TDREMOTE.EXE。我能够单步执行写入EGA/VGA CRT寄存器的指令,并观看效果,而无需在调试器窗口和用户屏幕之间切换


我不确定您想要实现什么,但在图形模式13h的非模拟DOS中,您可能会成功。

谢谢。这是因为,我不明白平面图形的真正含义:)。 当我选择平面2时,此代码工作正常:

mov ax, 00DH
int 010H

mov dx, 3CEH
mov al, 4H
out dx, al
mov dx, 3CFH
mov al, 1H
out dx, al

mov ax, 00A41H
mov bx, 2H
mov cx, 2H
int 010H

; I can read now pixel value from 00A0000H

事实上,我想实现几个tty(tty1,…,tty8),为此我使用虚拟8086和分页。多个tty可以同时处于不同的模式。我最初的想法是,当一个ring=3的程序wan要写入一个不是当前的tty时,我更改页表,将视频ram重定向到内部tty regen缓冲区。例如,在bochs中,当当前tty的分辨率为12H,且用户希望写入分辨率为3H的tty2时,使用此映射:

0x0000000000000000-0x000000000009ffff -> 0x000000000000-0x00000009ffff
0x00000000000a0000-0x00000000000b7fff -> 0x000000010000-0x000000027fff ; trick to avoid to clear the vram when chaning mode
0x00000000000b8000-0x00000000000bbfff -> 0x00000021c000-0x00000021ffff ; regen internal buffer
0x00000000000bc000-0x00000000000bffff -> 0x00000002c000-0x00000002ffff
0x00000000000c0000-0x000000000011ffff -> 0x0000000c0000-0x00000011ffff

多谢各位。这是因为,我不明白平面图形的真正含义:)。 当我选择平面2时,此代码工作正常:

mov ax, 00DH
int 010H

mov dx, 3CEH
mov al, 4H
out dx, al
mov dx, 3CFH
mov al, 1H
out dx, al

mov ax, 00A41H
mov bx, 2H
mov cx, 2H
int 010H

; I can read now pixel value from 00A0000H

事实上,我想实现几个tty(tty1,…,tty8),为此我使用虚拟8086和分页。多个tty可以同时处于不同的模式。我最初的想法是,当一个ring=3的程序wan要写入一个不是当前的tty时,我更改页表,将视频ram重定向到内部tty regen缓冲区。例如,在bochs中,当当前tty的分辨率为12H,且用户希望写入分辨率为3H的tty2时,使用此映射:

0x0000000000000000-0x000000000009ffff -> 0x000000000000-0x00000009ffff
0x00000000000a0000-0x00000000000b7fff -> 0x000000010000-0x000000027fff ; trick to avoid to clear the vram when chaning mode
0x00000000000b8000-0x00000000000bbfff -> 0x00000021c000-0x00000021ffff ; regen internal buffer
0x00000000000bc000-0x00000000000bffff -> 0x00000002c000-0x00000002ffff
0x00000000000c0000-0x000000000011ffff -> 0x0000000c0000-0x00000011ffff

在图形模式下,帧缓冲区保存像素而不是字符。所以当你从视频存储器中读取时,你当然会读取组成屏幕字符的像素,而不是ASCII码。有关模式
12h
中视频内存布局的说明,请参阅。是的,我知道没有ascii码值。但即使是像素值也不存在。在我的示例中,从未为
scasb
执行hlt,您应该使用
repne
repe
,而不是
rep
是的,我知道,但rep和repz是相同的操作码0F3H。通常,好的汇编程序与使用哪种汇编程序无关。这可能是正确的,但不是在错误的上下文中使用
rep
的好理由。可读性是您应该改用
repe
的原因。在图形模式下,帧缓冲区保存的是像素而不是字符。所以当你从视频存储器中读取时,你当然会读取组成屏幕字符的像素,而不是ASCII码。有关模式
12h
中视频内存布局的说明,请参阅。是的,我知道没有ascii码值。但即使是像素值也不存在。在我的例子中,hlt