【问题标题】:Character reading does not work in graphical mode字符读取在图形模式下不起作用
【发布时间】:2019-06-02 17:10:56
【问题描述】:

我想用ah=8 int 10h 中断读取一个字符及其属性。

它适用于文本模式,但不适用于图形模式(16 色 640 x 480)。

mov ax,0012h
int 10h       ;graphical mode
int 10h

mov ah,0Ah
mov al,'1'
mov cx,200    ;printing '1' 200 times
mov bx,0
int 10h

mov ah,2
mov dx,0      ;moving cursor to (0,0)
mov bx,0
int 10h

mov bh,0
mov ah,8      ;reading the character
int 10h

代码必须给AH=07h & AL=31h

但是这段代码总是给出AH=07h & AL=00h

那么如何在图形模式下使用这种方法呢?

【问题讨论】:

  • 以图形模式读回文本是不明智的。它有像素,而不是字符。即使是图形模式,您仍然可以写入字符,但不能将它们读回。
  • 如果我无法读取任何字符,如何在图形模式下制作文字处理器?
  • 只是不要将文档的文本存储在显存中,它属于普通内存。不仅仅是因为您无法阅读,还会出现超出屏幕大小的文本。
  • 你能给我一个想法吗?这对我真的很有帮助。
  • 最简单的形式:分配一个字符数组,并定义变量来跟踪光标位置。每次按键时,插入/删除数组中的字符和/或更新光标位置(无论是否适合按下的键)。根据新的数组内容和光标位置刷新屏幕。这可以在每次按键后完成,但通常情况下,程序会等到“安静”的时刻,并且只刷新已更改的区域。

标签: assembly emu8086 cursor-position dosbox


【解决方案1】:

问题简述

  • 写一个冗余的int 10h
  • 请求的复制计数太大
  • 在黑色背景上输出黑色字符
  • 解释随机寄存器内容

说明

...写一个多余的int 10h

mov ax,0012h
int 10h       ;graphical mode
int 10h

在没有明确指定函数号的情况下调用 api 函数绝不是一个好主意。您可能会认为在此示例中,AX 寄存器仍然保存 0012h(因为函数 00h 被记录为不返回任何内容),但情况并非总是如此。
我不知道你为什么写第二个int 10h。也许您已经删除了一些额外的说明,只是忘记了删除这个。可能发生...

...请求一个太大的复制计数

来自我的 VGA Programmer's Guide for BIOS.WriteCharacterOnly 0Ah:

在图形模式中,复制字符的次数,被限制在光标位置右侧直到行尾的剩余字符位置的数量。

您的程序指定复制计数为 200,这比屏幕上可用的 80 列多得多。请求过多会导致不可预测的行为。
您上一个问题中的screenshot for emu8086 已经显示了这个问题。仔细看图片的左上角。

以下是我的计算机 [1] 在我请求复制计数 81 时显示的内容。在正常显示 80 个字符后,该函数会环绕到屏幕的左边缘 但也下降一条扫描线(为 1 像素)!现在您可以看到屏幕左上角的 8x16 字符框不再包含 BIOS 函数 08h 可以识别为有效 ASCII 字符的位模式,因此函数 08h 将返回 AL=0

        x=0    x=7
        |      |
       .........................................
y=0 -  .                                        
       .                                        
       .           **      **      **      **   
       .   **     ***     ***     ***     ***   
       .  ***    ****    ****    ****    ****   
       . ****      **      **      **      **   
       .   **      **      **      **      **   
       .   **      **      **      **      **   
       .   **      **      **      **      **   
       .   **      **      **      **      **   
       .   **      **      **      **      **   
       .   **    ******  ******  ******  ****** 
       . ******                                 
       .                                        
       .                                        
y=15 - .                                        

请参阅this comment by Michael Petch,了解 BIOS 之间可能的实现差异。这是一个聪明的程序员,可以确保他的程序在各种各样的机器上运行良好。

...在黑色背景上输出黑色字符

当您调用 BIOS 函数 0Ah WriteCharacterOnly 时,“Only”仅适用于字母数字视频模式。在图形模式中,BL 寄存器中的值用于字符颜色。您的程序将 0(黑色)作为字符颜色传递,BIOS 将在黑色背景上使用它。这是无法从屏幕上读取内容的另一个原因。

...解读随机寄存器内容

来自我的 VGA Programmer's Guide for BIOS.ReadAttributeCharacterPair 08h:

当显示处于其中一种图形模式时,不返回属性代码。

您的程序处于图形模式(16 色 640x480)。您不应解释 AH 寄存器中的值。它是那里发生的任何事情,所以把它当作垃圾。在您的计算机上,此寄存器为 7,在我的 [1] 上为 5。

试试这个

您不需要将光标移动到屏幕的左上角,因为光标位置没有被函数 0Ah 修改。

mov     ax, 0012h  ; BIOS.SetVideoMode 16-color 640x480
int     10h
mov     cx, 80     ; Replication count
mov     bx, 000Eh  ; Display page 0, character color Yellow
mov     ax, 0A31h  ; BIOS.WriteCharacter(Only)
int     10h
mov     bh, 0      ; Display page 0
mov     ah, 08h    ; BIOS.Read(Attribute)Character(Pair)
int     10h        ; -> AL=31h

[1] Phoenix TrustedCore v1.23 VGA BIOS 1264

【讨论】:

  • 我无法读取字符,我只能读取 ah=07h 的属性。
  • @Roshan'sLastCheese 我重写了我的答案。希望这些新信息对您有所帮助!
  • 感谢您的回答,对我帮助很大!我写两次 int10h 的原因是它有一个错误。如果我不写两次,模拟器会打开 700x400 分辨率窗口。
  • @Roshan'sLastCheese 这确实是一个奇怪的错误/错误。
猜你喜欢
  • 1970-01-01
  • 2018-10-31
  • 1970-01-01
  • 2018-10-25
  • 1970-01-01
  • 2021-11-17
  • 1970-01-01
  • 2021-09-07
  • 1970-01-01
相关资源
最近更新 更多