生活随笔
收集整理的这篇文章主要介绍了
利用BIOS 中断INT 0x10显示字符和字符串
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
注:以下程序系原创,使用AT&T格式汇编来调用BIOS 0x10中断,如有错误,欢迎指正。表达能力较差,写的不好,但若能帮助一二访客,幸甚。
使用BIOS 显示服务(Video Service)--INT 10H,下面主要探究字符显示模式。
BIOS中断在保护模式下是不能用的,故不能在Linux中测试,所以写了个简单的boot loader,并在虚拟机中运行程序。
1.以电传的方式写入字符串(AH=0x13)
[cpp] view plaincopyprint?
------------------------------------------------------------------ INT 0x10功能0x13 -------------------------------------------------------------- 描述: 以电传打字机的方式显示字符串 接受参数: AH 0x13 AL 显示模式 BH 视频页 BL 属性值(如果AL=0x00或0x01) CX 字符串的长度 DH,DL 屏幕上显示起始位置的行、列值 ES:BP 字符串的段:偏移地址 返回值: 无 显示模式(AL): 0x00:字符串只包含字符码,显示之后不更新光标位置,属性值在BL中 0x01:字符串只包含字符码,显示之后更新光标位置,属性值在BL中 0x02:字符串包含字符码及属性值,显示之后不更新光标位置 0x03:字符串包含字符码及属性值,显示之后更新光标位置 -------------------------------------------------------------------
示例:
[cpp] view plaincopyprint?
# A bootsect, which print a string by BIOS interrupt video services(int 0x10) .section .text .global _start .code16 _start: movw %cx, %ax movw %ax, %ds movw %ax, %es movw $msgstr,%bp movw len, %cx movb $0x05, %dh movb $0x08, %dl movb $0x01, %al movb $0x13, %ah movb $0x01, %bl movb $0x00, %bh int $0x10 1: jmp 1b msgstr: .asciz "Hello babyos(print by BIOS int 0x10:0x13, mode 0x01)!" len: .int . - msgstr .org 0x1fe, 0x90 .word 0xaa55 makefile: all: boot.img boot.o: boot.s as -o $@ $< boot: boot.o ld --oformat binary -N -Ttext 0x7c00 -o $@ $< boot.img: boot dd if=boot of=boot.img bs=512 count=1 clean: rm ./boot ./boot.img ./boot.o
运行:
2.通过功能号0x09探究色彩控制
上面的显示为什么是红色呢?我们可以通过实验来看一下颜色控制。
[cpp] view plaincopyprint?
------------------------------------------------------------------------ INT 0x10功能0x09 ------------------------------------------------------------------- 描述: 显示字符并设置其属性 接受参数: AH 0x09 AL 字符的ASCII码 BH 视频页 BL 属性值 CX 重复次数 返回值: 无 注意: 在显示字符之后并不前进光标。在文本和图形模式下均可调用该功能 显示完字符后,如果还要继续显示字符,必须调用INT 0x10功能0x02前进光标 ------------------------------------------------------------------------- ------------------------------------------------------------------------ INT 0x10功能0x02 ------------------------------------------------------------------- 描述: 把光标定位在选定视频页的特定行列位置 接受参数: AH 0x02 DH,DL 行、列值 BH 视频页 返回值: 无 注意: 在80x25模式下,DH范围0~24,DL范围0~79 -------------------------------------------------------------------------
示例:
实现一个从第4行~7行,第8列~71列,显示‘A’~‘Z’的程序,共显示256个字符,使用BL(0~255)
C 伪代码:
[cpp] view plaincopyprint?
cx = 0x04; bh = 0x00; dh = 0x04; dl = 0x08; al = 'A'; for (bl = 0; bl < 256; bl++) { print_char(); al++; if (al == 'Z') al = 'A'; dl++; if (dl == 72) { dh++; dl = 4; } set_cursor(); }
汇编代码:
[cpp] view plaincopyprint?
# A bootsect, which print a colorful chars by BIOS INT 0x10, 0x09 .section .text .global _start .code16 _start: movw %cx, %ax movw %ax, %ds movw %ax, %es movw $0x01, %cx # 字符显示重复次数 movb $0x00, %bh # 视频页 movb $0x04, %dh # 显示起始行 movb $0x08, %dl # 显示起始列 movb $'A', %al # 显示字符 movb $0x00, %bl # 属性值 1: call print_char incb %al cmpb $'Z', %al jne 2f movb $'A', %al 2: incb %dl cmpb $72, %dl jne 3f movb $8, %dl incb %dh 3: call set_cursor incb %bl cmp $256, %bl jne 1b jmp 1f print_char: movb $0x09, %ah int $0x10 ret set_cursor: movb $0x02, %ah int $0x10 ret 1: jmp 1b .org 0x1fe, 0x90 .word 0xaa55
结果:
可以显式地验证色彩控制BL:
[cpp] view plaincopyprint?
7 6 5 4 3 2 1 0 I R G B I R G B 闪烁 R G B I R G B
如上图所示,7~4位为背景色,I表示高亮,RGB表示红绿蓝,若显卡支持闪烁,则位7表示是否闪烁。
色彩混合:
[cpp] view plaincopyprint?
----------------------------------------------------------- 混合的三种基色 不开启亮度位 开启亮度位 ------------------------------------------------------- 红+绿+蓝 浅灰 白色 绿+蓝 青色 浅青 红+蓝 洋红 浅洋红 红+绿 棕色 黄色 无色彩 黑色 暗灰 -----------------------------------------------------------
3.清屏
可以发现屏幕上有许多Bochs的打印信息,看着不爽,想办法去掉它们。
利用0x06号功能,上卷全部行,则可清屏。
-----------------------------------------------------------
INT 0x10 功能0x06
------------------------------------------------------
描述:
上卷窗口
参数:
AH 6
AL 上卷的行数(0表示全部)
BH 空白区域的视频属性
CH,CL 窗口左上角的行列位置
DH,DL 窗口右下角的行列位置
返回值:
无
------------------------------------------------------------
示例:
[cpp] view plaincopyprint?
# A bootsect, which print a colorful chars by BIOS INT 0x10, 0x09 .section .text .global _start .code16 _start: movw %cx, %ax movw %ax, %ds movw %ax, %es call clear_screen # 清屏 movw $0x01, %cx # 字符显示重复次数 movb $0x00, %bh # 视频页 movb $0x04, %dh # 显示起始行 movb $0x08, %dl # 显示起始列 movb $'A', %al # 显示字符 movb $0x00, %bl # 属性值 1: call print_char # 打印字符 incb %al # 下一个字符 cmpb $'Z', %al # 是否该重新从‘A’开始 jne 2f movb $'A', %al 2: incb %dl # 下一个位置 cmpb $72, %dl # 是否到下一行 jne 3f movb $8, %dl incb %dh 3: call set_cursor # 设置光标位置 incb %bl # 下一种属性 cmp $0, %bl # 是否256种属性用完 jne 1b jmp 1f # 结束 clear_screen: # 清屏函数 movb $0x06, %ah # 功能号0x06 movb $0, %al # 上卷全部行,即清屏 movb $0, %ch # 左上角行 movb $0, %ch # 左上角列 movb $24, %dh # 右下角行 movb $79, %dl # 右下角列 movb $0x07, %bh # 空白区域属性 int $0x10 ret print_char: movb $0x09, %ah # 功能号0x09 int $0x10 ret set_cursor: movb $0x02, %ah # 功能号0x02 int $0x10 ret 1: jmp 1b .org 0x1fe, 0x90 .word 0xaa55
结果:
4.直接写显存绘制字符串:
示例:
[cpp] view plaincopyprint?
#--------------------------------------------------------------- # 直接写显存显示一些文字函数: # 显示计算机当前工作的显示模式 draw_some_text: # 设置ES,DS的值 movw $VIDEO_SEG_TEXT,%ax movw %ax, %es xorw %ax, %ax movw %ax, %ds # 计算字符显示位置的显存地址(目标地址) movw $((80*TEXT_ROW+TEXT_COL) * 2), %di # 源字符串地址 leaw msgstr, %si movb $TEXT_COLOR, %al # 属性值(颜色) movw len, %cx # 显示的字符个数 draw_a_char: movsb stosb loop draw_a_char ret
总结
以上是生活随笔为你收集整理的利用BIOS 中断INT 0x10显示字符和字符串的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。