利用BIOS 中断INT 0x10显示字符和字符串

本文 转载自 https://blog.csdn.net/guzhou_diaoke/article/details/8397658


使用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= 0x000x01
  11. CX 字符串的长度
  12. DH,DL 屏幕上显示起始位置的行、列值
  13. ES:BP 字符串的段:偏移地址
  14. 返回值:
  15. 显示模式(AL):
  16. 0x00:字符串只包含字符码,显示之后不更新光标位置,属性值在BL中
  17. 0x01:字符串只包含字符码,显示之后更新光标位置,属性值在BL中
  18. 0x02:字符串包含字符码及属性值,显示之后不更新光标位置
  19. 0x03:字符串包含字符码及属性值,显示之后更新光标位置
  20. -------------------------------------------------------------------

示例:

  
  
  1. # A bootsect, which print a string by BIOS interrupt video services(int 0x10)
  2. .section .text
  3. .global _start
  4. .code16
  5. _start:
  6. movw %cx, %ax
  7. movw %ax, %ds
  8. movw %ax, %es
  9. movw $msgstr,%bp
  10. movw len, %cx
  11. movb $0x05, %dh
  12. movb $0x08, %dl
  13. movb $0x01, %al
  14. movb $0x13, %ah
  15. movb $0x01, %bl
  16. movb $0x00, %bh
  17. int $0x10
  18. 1:
  19. jmp 1b
  20. msgstr:
  21. .asciz "Hello babyos(print by BIOS int 0x10:0x13, mode 0x01)!"
  22. len:
  23. .int . - msgstr
  24. .org 0x1fe, 0x90
  25. .word 0xaa55
  26. makefile:
  27. all: boot.img
  28. boot.o: boot.s
  29. as -o $@ $<
  30. boot: boot.o
  31. ld --oformat binary -N -Ttext 0x7c00 -o $@ $<
  32. boot.img: boot
  33. dd if=boot of=boot.img bs= 512 count= 1
  34. clean:
  35. 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. 显示完字符后,如果还要继续显示字符,必须调用INT 0x10功能 0x02前进光标
  16. -------------------------------------------------------------------------
  17. ------------------------------------------------------------------------
  18. INT 0x10功能 0x02
  19. -------------------------------------------------------------------
  20. 描述:
  21. 把光标定位在选定视频页的特定行列位置
  22. 接受参数:
  23. AH 0x02
  24. DH,DL 行、列值
  25. BH 视频页
  26. 返回值:
  27. 注意:
  28. 80x25模式下,DH范围 024,DL范围 079
  29. -------------------------------------------------------------------------

示例:

扫描二维码关注公众号,回复: 5004725 查看本文章

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

C 伪代码:

  
  
  1. cx = 0x04;
  2. bh = 0x00;
  3. dh = 0x04;
  4. dl = 0x08;
  5. al = 'A';
  6. for (bl = 0; bl < 256; bl++)
  7. {
  8. print_char();
  9. al++;
  10. if (al == 'Z')
  11. al = 'A';
  12. dl++;
  13. if (dl == 72)
  14. {
  15. dh++;
  16. dl = 4;
  17. }
  18. set_cursor();
  19. }
汇编代码:

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


猜你喜欢

转载自blog.csdn.net/m0_37329910/article/details/86081024