利用BIOS 中断INT 0x10显示字符和字符串
2016-08-23 11:14
801 查看
注:以下程序系原创,使用AT&T格式汇编来调用BIOS 0x10中断,如有错误,欢迎指正。表达能力较差,写的不好,但若能帮助一二访客,幸甚。
使用BIOS 显示服务(Video Service)--INT 10H,下面主要探究字符显示模式。
BIOS中断在保护模式下是不能用的,故不能在Linux中测试,所以写了个简单的boot loader,并在虚拟机中运行程序。
view plain
copy
print?
------------------------------------------------------------------
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 plain
copy
print?
# 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
运行:
[cpp]
view plain
copy
print?
------------------------------------------------------------------------
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 plain
copy
print?
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 plain
copy
print?
# 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 plain
copy
print?
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 plain
copy
print?
-----------------------------------------------------------
混合的三种基色 不开启亮度位 开启亮度位
-------------------------------------------------------
红+绿+蓝 浅灰 白色
绿+蓝 青色 浅青
红+蓝 洋红 浅洋红
红+绿 棕色 黄色
无色彩 黑色 暗灰
-----------------------------------------------------------
利用0x06号功能,上卷全部行,则可清屏。
-----------------------------------------------------------
INT 0x10 功能0x06
------------------------------------------------------
描述:
上卷窗口
参数:
AH 6
AL 上卷的行数(0表示全部)
BH 空白区域的视频属性
CH,CL 窗口左上角的行列位置
DH,DL 窗口右下角的行列位置
返回值:
无
------------------------------------------------------------
示例:
[cpp]
view plain
copy
print?
# 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
结果:
[cpp]
view plain
copy
print?
#---------------------------------------------------------------
# 直接写显存显示一些文字函数:
# 显示计算机当前工作的显示模式
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 显示服务(Video Service)--INT 10H,下面主要探究字符显示模式。
BIOS中断在保护模式下是不能用的,故不能在Linux中测试,所以写了个简单的boot loader,并在虚拟机中运行程序。
1.以电传的方式写入字符串(AH=0x13)
[cpp]view plain
copy
print?
------------------------------------------------------------------
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 plain
copy
print?
# 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 plain
copy
print?
------------------------------------------------------------------------
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 plain
copy
print?
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 plain
copy
print?
# 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 plain
copy
print?
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 plain
copy
print?
-----------------------------------------------------------
混合的三种基色 不开启亮度位 开启亮度位
-------------------------------------------------------
红+绿+蓝 浅灰 白色
绿+蓝 青色 浅青
红+蓝 洋红 浅洋红
红+绿 棕色 黄色
无色彩 黑色 暗灰
-----------------------------------------------------------
3.清屏
可以发现屏幕上有许多Bochs的打印信息,看着不爽,想办法去掉它们。利用0x06号功能,上卷全部行,则可清屏。
-----------------------------------------------------------
INT 0x10 功能0x06
------------------------------------------------------
描述:
上卷窗口
参数:
AH 6
AL 上卷的行数(0表示全部)
BH 空白区域的视频属性
CH,CL 窗口左上角的行列位置
DH,DL 窗口右下角的行列位置
返回值:
无
------------------------------------------------------------
示例:
[cpp]
view plain
copy
print?
# 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 plain
copy
print?
#---------------------------------------------------------------
# 直接写显存显示一些文字函数:
# 显示计算机当前工作的显示模式
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
相关文章推荐
- babyos (一)——利用BIOS 中断INT 0x10显示字符和字符串
- babyos (一)——利用BIOS 中断INT 0x10显示字符和字符串
- 使用BIOS中断显示字符串笔记(int 10h 13号中断)
- 利用中断16H,显示按下的某个键的扫描码和ASCII码(以十六进制形式),以及这个字符(如果存在可显示的形式),直到按下ESC键后程序退出。(别人的作业,我帮着做的)
- 调用 BIOS 视频中断向量(int 10h)输出字符串
- 对调用INT 10H中断显示字符串的优化
- 利用BIOS中断或DOS中断实现一个显示当前时间的程序
- 编写并安装int 7ch中断例程,功能为显示一个用0结束的字符串,中断例程安装在0:200处
- 对调用INT 10H中断显示字符串的优化
- c++中字符数组或者字符串中的内容在VS debug环境中不能完全显示
- javascript利用正则快速找出两个字符串的不同字符
- asp.net(c#)字符串转换成字符数组 字符串转换成int 数组
- int 10H 显示字符串功能在《自己动手写OS》第五章代码中的分析
- asp.net(c#) datelist DataGrid 中截取字符串加"..." 和 鼠标放上去字符全部显示
- 写了一个字符串截取一定长度的代码,中文两个字符,英文一个字符,如果截断了自动用一个.或两个.来对齐,用于标题的显示
- 字符串显示一个字符效果
- asp.net(c#)字符串转换成字符数组 字符串转换成int 数组
- 字符串字符显示与16进制显示之间的相互转换
- 利用正则快速找出两个字符串的不同字符
- asp.net(c#) datelist DataGrid 中截取字符串加"..." 和 鼠标放上去字符全部显示