babyos (一)——利用BIOS 中断INT 0x10显示字符和字符串

babyos (一)——利用BIOS 中断INT 0x10显示字符和字符串

http://blog.csdn.net/guzhou_diaoke/article/details/8397658

注:以下程序系原创,使用AT&T格式汇编来调用BIOS 0x10中断,如有错误,欢迎指正。表达能力较差,写的不好,但若能帮助一二访客,幸甚。


使用BIOS 显示服务(Video Service)--INT 10H,下面主要探究字符显示模式。

BIOS中断在保护模式下是不能用的,故不能在Linux中测试,所以写了个简单的boot loader,并在虚拟机中运行程序。


1.以电传的方式写入字符串(AH=0x13)

  1. ------------------------------------------------------------------  
  2.             INT 0x10功能0x13  
  3. --------------------------------------------------------------  
  4. 描述:  
  5.     以电传打字机的方式显示字符串  
  6. 接受参数:  
  7.     AH          0x13  
  8.     AL          显示模式  
  9.     BH          视频页  
  10.     BL          属性值(如果AL=0x00或0x01)  
  11.     CX          字符串的长度  
  12.     DH,DL       屏幕上显示起始位置的行、列值  
  13.     ES:BP       字符串的段:偏移地址  
  14. 返回值:  
  15.     无  
  16. 显示模式(AL):  
  17.     0x00:字符串只包含字符码,显示之后不更新光标位置,属性值在BL中  
  18.     0x01:字符串只包含字符码,显示之后更新光标位置,属性值在BL中  
  19.     0x02:字符串包含字符码及属性值,显示之后不更新光标位置  
  20.     0x03:字符串包含字符码及属性值,显示之后更新光标位置  
  21. -------------------------------------------------------------------  

示例:
  1. # A bootsect, which print a string by BIOS interrupt video services(int 0x10)  
  2.   
  3. .section .text  
  4. .global _start  
  5. .code16  
  6.   
  7. _start:  
  8.     movw    %cx,    %ax  
  9.     movw    %ax,    %ds  
  10.     movw    %ax,    %es  
  11.   
  12.     movw    $msgstr,%bp  
  13.     movw    len,    %cx  
  14.     movb    $0x05,  %dh  
  15.     movb    $0x08,  %dl  
  16.     movb    $0x01,  %al  
  17.     movb    $0x13,  %ah  
  18.     movb    $0x01,  %bl  
  19.     movb    $0x00,  %bh  
  20.   
  21.     int     $0x10  
  22. 1:  
  23.     jmp     1b  
  24.   
  25. msgstr:  
  26.     .asciz  "Hello babyos(print by BIOS int 0x10:0x13, mode 0x01)!"  
  27. len:  
  28.     .int    . - msgstr  
  29.   
  30.     .org    0x1fe,  0x90  
  31.     .word   0xaa55  
  32.   
  33. makefile:  
  34. all: boot.img  
  35.   
  36. boot.o: boot.s  
  37.     as -o $@ $<  
  38.   
  39. boot: boot.o  
  40.     ld --oformat binary -N -Ttext 0x7c00 -o $@ $<  
  41.   
  42. boot.img: boot  
  43.     dd if=boot of=boot.img bs=512 count=1  
  44.   
  45. clean:  
  46.     rm ./boot ./boot.img ./boot.o  

运行:


2.通过功能号0x09探究色彩控制

上面的显示为什么是红色呢?我们可以通过实验来看一下颜色控制。

  1. ------------------------------------------------------------------------  
  2.             INT 0x10功能0x09  
  3. -------------------------------------------------------------------  
  4. 描述:  
  5.     显示字符并设置其属性  
  6. 接受参数:  
  7.     AH          0x09  
  8.     AL          字符的ASCII码  
  9.     BH          视频页  
  10.     BL          属性值  
  11.     CX          重复次数  
  12. 返回值:  
  13.     无  
  14. 注意:  
  15.     在显示字符之后并不前进光标。在文本和图形模式下均可调用该功能  
  16.     显示完字符后,如果还要继续显示字符,必须调用INT 0x10功能0x02前进光标  
  17. -------------------------------------------------------------------------  
  18.   
  19. ------------------------------------------------------------------------  
  20.             INT 0x10功能0x02  
  21. -------------------------------------------------------------------  
  22. 描述:  
  23.     把光标定位在选定视频页的特定行列位置  
  24. 接受参数:  
  25.     AH          0x02  
  26.     DH,DL       行、列值  
  27.     BH          视频页  
  28. 返回值:  
  29.     无  
  30. 注意:  
  31.     在80x25模式下,DH范围0~24,DL范围0~79  
  32. -------------------------------------------------------------------------  

示例:

实现一个从第4行~7行,第8列~71列,显示‘A’~‘Z’的程序,共显示256个字符,使用BL(0~255)

C 伪代码:
  1. cx = 0x04;  
  2. bh = 0x00;  
  3.   
  4. dh = 0x04;  
  5. dl = 0x08;  
  6. al = 'A';  
  7.   
  8. for (bl = 0; bl < 256; bl++)  
  9. {  
  10.     print_char();  
  11.       
  12.     al++;  
  13.     if (al == 'Z')  
  14.         al = 'A';  
  15.       
  16.     dl++;  
  17.     if (dl == 72)  
  18.     {  
  19.         dh++;  
  20.         dl = 4;  
  21.     }  
  22.       
  23.     set_cursor();  
  24. }  
汇编代码:
  1. # A bootsect, which print a colorful chars by BIOS INT 0x10, 0x09  
  2.   
  3. .section .text  
  4. .global _start  
  5. .code16  
  6.   
  7. _start:  
  8.     movw    %cx,    %ax  
  9.     movw    %ax,    %ds  
  10.     movw    %ax,    %es  
  11.   
  12.     movw    $0x01,  %cx     # 字符显示重复次数  
  13.     movb    $0x00,  %bh     # 视频页  
  14.       
  15.     movb    $0x04,  %dh     # 显示起始行  
  16.     movb    $0x08,  %dl     # 显示起始列  
  17.       
  18.     movb    $'A',   %al     # 显示字符  
  19.     movb    $0x00,  %bl     # 属性值  
  20.   
  21. 1:  
  22.     call    print_char  
  23.     incb    %al  
  24.     cmpb    $'Z',   %al  
  25.     jne     2f  
  26.     movb    $'A',   %al  
  27. 2:    
  28.     incb    %dl  
  29.     cmpb    $72,    %dl  
  30.     jne     3f  
  31.     movb    $8,     %dl  
  32.     incb    %dh  
  33. 3:  
  34.     call    set_cursor  
  35.     incb    %bl  
  36.     cmp     $256,   %bl  
  37.     jne     1b  
  38.     jmp     1f  
  39.   
  40. print_char:  
  41.     movb    $0x09,  %ah  
  42.     int     $0x10  
  43.     ret  
  44.   
  45. set_cursor:  
  46.     movb    $0x02,  %ah  
  47.     int     $0x10  
  48.     ret  
  49.   
  50. 1:  
  51.     jmp     1b  
  52.   
  53.     .org    0x1fe,  0x90  
  54.     .word   0xaa55  

结果:


可以显式地验证色彩控制BL:
  1. 7       6       5       4       3       2       1       0  
  2. I       R       G       B       I       R       G       B  
  3. 闪烁    R     G       B       I       R       G       B  

如上图所示,7~4位为背景色,I表示高亮,RGB表示红绿蓝,若显卡支持闪烁,则位7表示是否闪烁。
色彩混合:
  1. -----------------------------------------------------------  
  2. 混合的三种基色     不开启亮度位      开启亮度位  
  3. -------------------------------------------------------  
  4. 红+绿+蓝           浅灰              白色  
  5. 绿+蓝             青色              浅青  
  6. 红+蓝             洋红              浅洋红  
  7. 红+绿             棕色              黄色  
  8. 无色彩             黑色              暗灰  
  9. -----------------------------------------------------------  

3.清屏

可以发现屏幕上有许多Bochs的打印信息,看着不爽,想办法去掉它们。

利用0x06号功能,上卷全部行,则可清屏。

-----------------------------------------------------------
INT 0x10 功能0x06
------------------------------------------------------
描述:
上卷窗口
参数:
AH 6
AL 上卷的行数(0表示全部)
BH 空白区域的视频属性
CH,CL 窗口左上角的行列位置
DH,DL 窗口右下角的行列位置
返回值:

------------------------------------------------------------
示例:

  1. # A bootsect, which print a colorful chars by BIOS INT 0x10, 0x09  
  2.   
  3. .section .text  
  4. .global _start  
  5. .code16  
  6.   
  7. _start:  
  8.     movw    %cx,    %ax  
  9.     movw    %ax,    %ds  
  10.     movw    %ax,    %es  
  11.   
  12.     call    clear_screen    # 清屏  
  13.   
  14.     movw    $0x01,  %cx     # 字符显示重复次数  
  15.     movb    $0x00,  %bh     # 视频页  
  16.       
  17.     movb    $0x04,  %dh     # 显示起始行  
  18.     movb    $0x08,  %dl     # 显示起始列  
  19.       
  20.     movb    $'A',   %al     # 显示字符  
  21.     movb    $0x00,  %bl     # 属性值  
  22.   
  23. 1:  
  24.     call    print_char      # 打印字符  
  25.     incb    %al             # 下一个字符  
  26.     cmpb    $'Z',   %al     # 是否该重新从‘A’开始  
  27.     jne     2f  
  28.     movb    $'A',   %al  
  29. 2:    
  30.     incb    %dl             # 下一个位置  
  31.     cmpb    $72,    %dl     # 是否到下一行  
  32.     jne     3f  
  33.     movb    $8,     %dl  
  34.     incb    %dh  
  35. 3:  
  36.     call    set_cursor      # 设置光标位置  
  37.     incb    %bl             # 下一种属性  
  38.     cmp     $0,     %bl     # 是否256种属性用完  
  39.     jne     1b  
  40.     jmp     1f              # 结束  
  41.   
  42. clear_screen:               # 清屏函数  
  43.     movb    $0x06,  %ah     # 功能号0x06  
  44.     movb    $0,     %al     # 上卷全部行,即清屏  
  45.     movb    $0,     %ch     # 左上角行  
  46.     movb    $0,     %ch     # 左上角列    
  47.     movb    $24,    %dh     # 右下角行  
  48.     movb    $79,    %dl     # 右下角列  
  49.     movb    $0x07,  %bh     # 空白区域属性  
  50.     int     $0x10  
  51.     ret  
  52.   
  53. print_char:  
  54.     movb    $0x09,  %ah     # 功能号0x09  
  55.     int     $0x10  
  56.     ret  
  57.   
  58. set_cursor:  
  59.     movb    $0x02,  %ah     # 功能号0x02  
  60.     int     $0x10  
  61.     ret  
  62.   
  63. 1:  
  64.     jmp     1b  
  65.   
  66.     .org    0x1fe,  0x90  
  67.     .word   0xaa55  

结果:


4.直接写显存绘制字符串:

示例:
  1. #---------------------------------------------------------------  
  2. # 直接写显存显示一些文字函数:  
  3. #   显示计算机当前工作的显示模式    
  4. draw_some_text:  
  5.     # 设置ES,DS的值  
  6.     movw    $VIDEO_SEG_TEXT,%ax  
  7.     movw    %ax,            %es  
  8.     xorw    %ax,            %ax  
  9.     movw    %ax,            %ds  
  10.   
  11.   
  12.     # 计算字符显示位置的显存地址(目标地址)  
  13.     movw    $((80*TEXT_ROW+TEXT_COL) * 2),  %di  
  14.       
  15.     # 源字符串地址  
  16.     leaw    msgstr,         %si  
  17.       
  18.     movb    $TEXT_COLOR,    %al     # 属性值(颜色)  
  19.     movw    len,            %cx     # 显示的字符个数  
  20.   
  21.   
  22. draw_a_char:              
  23.     movsb  
  24.     stosb  
  25.     loop    draw_a_char  
  26.   
  27.   
  28.     ret  
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值