查看“Text Mode Cursor”的源代码
←
Text Mode Cursor
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
光标会自动移动到最后一个书写字符之后的一个位置。在[[text mode|文本模式]]中,光标的工作方式与高级语言中不同。 它只是一个可由操作系统调整大小、显示、隐藏和移动的闪烁区域。 == 通过[[BIOS]]== 要使用BIOS操作光标,请使用int 0x10,屏幕功能的中断。 ===启用游标=== 启用光标功能还允许您设置开始和结束扫描线,即光标开始和结束的行。 最高处扫描线为0,最低处扫描线为最大扫描线(通常为15)。 * AH = 0x01 * CH = start scanline * CL = end scanline ===禁用光标=== * AH = 0x01 * CH = 0x3F (bits 0-7 unused, bit 5 disables cursor, bits 0-4 control cursor shape) === 移动光标 === * AH = 0x02 * BH = display page (usually, if not always 0) * DH = row * DL = column ===获取光标数据=== * AH = 0x03 * BH = display page (usually, if not always 0) 返回值: * CH = start scanline * CL = end scanline * DH = row * DL = column == 不通过[[BIOS]] == 在没有BIOS访问的情况下,操作光标需要将数据直接发送到硬件。 ===启用光标=== 启用游标功能还允许您设置开始和结束扫描线,即游标开始和结束的行。 最高处扫描线为0,最低处扫描线为最大扫描线(通常为15)。 '''C语言源代码''' <source lang="c"> void enable_cursor(uint8_t cursor_start, uint8_t cursor_end) { outb(0x3D4, 0x0A); outb(0x3D5, (inb(0x3D5) & 0xC0) | cursor_start); outb(0x3D4, 0x0B); outb(0x3D5, (inb(0x3D5) & 0xE0) | cursor_end); } </source> === 禁用光标 === '''C语言源代码''' <source lang="c"> void disable_cursor() { outb(0x3D4, 0x0A); outb(0x3D5, 0x20); } </source> '''汇编源代码''' <source lang="asm"> disable_cursor: pushf push eax push edx mov dx, 0x3D4 mov al, 0xA ; low cursor shape register out dx, al inc dx mov al, 0x20 ; bits 6-7 unused, bit 5 disables the cursor, bits 0-4 control the cursor shape out dx, al pop edx pop eax popf ret </source> === 移动光标 === 请记住,不需要每次显示新字符时都更新光标的位置。 相反,只在打印完整个字符串之后才更新它会更快。 '''Source in C''' <source lang="c"> void update_cursor(int x, int y) { uint16_t pos = y * VGA_WIDTH + x; outb(0x3D4, 0x0F); outb(0x3D5, (uint8_t) (pos & 0xFF)); outb(0x3D4, 0x0E); outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF)); } </source> '''汇编中的源代码''' <source lang="asm"> Cursor: VGA.Width equ 80 .SetCoords: ; input bx = x, ax = y ; modifies ax, bx, dx mov dl, VGA.Width mul dl add bx, ax .SetOffset: ; input bx = cursor offset ; modifies al, dx mov dx, 0x03D4 mov al, 0x0F out dx, al inc dl mov al, bl out dx, al dec dl mov al, 0x0E out dx, al inc dl mov al, bh out dx, al ret </source> ===获取光标位置=== 使用此代码,您将获得:<tt>pos = y * VGA_WIDTH + x</tt>。 要获得坐标,只需计算: <tt>y = pos / VGA_WIDTH; x = pos % VGA_WIDTH;</tt>. '''C语言源代码''' <source lang="c"> uint16_t get_cursor_position(void) { uint16_t pos = 0; outb(0x3D4, 0x0F); pos |= inb(0x3D5); outb(0x3D4, 0x0E); pos |= ((uint16_t)inb(0x3D5)) << 8; return pos; } </source> ==基于字体的“图形”光标== === 用途 === 在DOS时代,完全不使用硬件VGA光标是很常见的,而是覆盖VGA字体来创建箭头指针,就像在图形模式中一样。 例如,在[https://en.wikipedia.org/wiki/Norton_Utilities Norton Utilities]或[[Norton Diskedit]]的DOS版本中使用了该技术。 [[Image:Itmouse.png|Arrow cursor in text mode]] 您可以通过光标颜色轻松地发现此字体更改光标: 由于只有字体被更改,属性字节未被触及,指针在移动时会改变颜色。 这里是论坛[https://forum.osdev.org/download/file.php?id=2264&mode=view TUI的另一个例子,具有8x8个字符和指形光标] === 如何实现 === 基本原理是从屏幕上存储4个字节(2x2),将它们的[[VGA Fonts|VGA字体]]复制到一些未使用的方框图字符(0xC0-0xDF),或者将箭头屏蔽,然后在屏幕上写入这些2x2方框图字符。 然后,当鼠标移动时,屏幕上恢复原来的4个字节,整个过程在新位置重复。 使用框绘制字符很重要,因为通常VGA将字体显示为9x16,添加了一个空的第9列,这将导致光标中的 “间隙”。 对于方框图字符,第9列是第8列的副本,因此不会将指针一分为二。 如果您使用8x8字符(如80x50或132x50模式),则没有字符分隔栏,您可以随意使用任何字符。 在上面的论坛示例中,您可以在字符0xF0-0xF3处发现ASCII表上的光标。 尽管箭头大小与一个字符(通常为8x16或8x8)相同,但由于指针可以以像素精度移动,它可以在水平和垂直方向与下一个字符重叠,因此总共需要4个字节: <pre> char 1 attr 1 char 2 attr 2 ........|????????|........|???????? first line ........|????????|........|???????? (note attribute bytes are untouched) ........|????????|........|???????? ....x...|????????|........|???????? ....xx..|????????|........|???????? ....xxx.|????????|........|???????? ....xxxx|????????|........|???????? ....xxxx|????????|x.......|???????? --------+--------+--------+-------- ....xxxx|????????|xx......|???????? second line ....xxxx|????????|xxx.....|???????? ....xxxx|????????|xxxx....|???????? .......x|????????|x.......|???????? .......x|????????|x.......|???????? ........|????????|xx......|???????? ........|????????|........|???????? ........|????????|........|???????? char 3 attr 3 char 4 attr 4 </pre> 您可以使用BIOS读取VGA字体,或者如果您已经处于保护模式,则可以使用VGA寄存器读取VGA字体。 阅读 [[VGA Fonts|VGA字体]] 文章了解更多信息。 通过将鼠标光标除以字体大小来计算字符位置:cx=mx/8和cy=my/16。 然后计算my%16以获得要修改的字体字形的第一个字节,并计算mx%8以获得您必须按其移位箭头掩码的移位值。 == 关于GRUB的提醒 == 如果grub.cfg中的timeout设置为0,光标将被禁用,您需要自己启用它。 其它情况下,[[GRUB]]将为您启用光标。 由于这种不一致,因此始终启用光标是一个好主意。 即使没有将超时设置为0,将来也可能需要,或者有人可能会在他们的系统上更改timeout。 == 另见 == * [[VGA Hardware|VGA硬件]] * [[Text UI]] ===外部链接=== * http://www.osdever.net/FreeVGA/vga/textcur.htm * https://web.archive.org/web/20080731014051/http://www.bookcase.com:80/library/dos/ints/int10.html * https://web.archive.org/web/20120324083032/http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_13/CH13-2.html * https://en.wikipedia.org/wiki/VGA-compatible_text_mode [[Category:Video]] [[Category:Text UI]] [[Category:VGA]]
返回至“
Text Mode Cursor
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
变体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
工具
链入页面
相关更改
特殊页面
页面信息