使用BIOS以及直接写显存绘制图形

注:以下程序系由相应的Intel格式汇编改编而来,略有修改,若发现bug,欢迎指正。若有问题,欢迎交流。若能帮助一二访客,幸甚。


一年前仿照Skelix 写过一个简单的内核,并命名为BabyOS。当时代码大部分用的Skelix的,终究有些遗憾,所以想趁今年寒假--工作前最后一个假期,重新实现一下BabyOS,力求尽量用自己的代码实现。所以前几天学习了一下AT&T 汇编、内联汇编及C与汇编的相互调用。下一个问题就是显示,经过许多考虑,这次准备尝试一下图形界面的系统(因为看上去更有趣些),或许有点舍本求末的嫌疑,但我写个OS kernel主要是好玩,从未想有正式应用,所以怎么好玩就怎么来。

昨晚研究了下BIOS INT 0x10显示字符,今晚决定不管有用没有先学习一下BIOS INT 0x10及实模式下写显存来显示图形的知识。

1.绘制像素

  1. -----------------------------------------------------------------------  
  2.                         INT 0x10可识别的视频图形模式  
  3. --------------------------------------------------------------------  
  4. 模式          分辨率(列*行,像素)   颜色数  
  5. 6                   640x200                 2  
  6. 0DH                 320x200                 16  
  7. 0EH                 640x350                 16  
  8. 0FH                 640x350                 2  
  9. 10H                 640x200                 16  
  10. 11H                 640x480                 2  
  11. 12H                 640x480                 16  
  12. 13H                 320x200                 256  
  13. 6AH                 800x600                 16  
  14. -----------------------------------------------------------------------  
当视频控制器处于图形模式时,INT 0x10的功能0CH在屏幕上绘制一个像素点。(功能0CH执行的相当慢)

  1. -----------------------------------------------------------------------  
  2.                         INT 0x10 功能0CH  
  3. ---------------------------------------------------------------  
  4. 描述:  
  5.     写像素  
  6. 接受参数:  
  7.     AH          0CH  
  8.     AL          像素值  
  9.     BH          视频页  
  10.     CX          X坐标  
  11.     DX          Y坐标  
  12. 返回值:  
  13.     无  
  14. 注意:  
  15.     视频显示必须处于图形模式下。像素值的范围和坐标范围与当前的图形模式有关。  
  16.     如果AL的位7置位,新的像素同当前像素的内容进行异或运算。  
  17. -------------------------------------------------------------------------  

示例,画线程序:
  1. # This program draws a straight line in graphics mode.  
  2. # 2012-12-24 20:42  
  3. # guzhoudiaoke@126.com  
  4.   
  5. .section .text  
  6. .global _start  
  7. .code16  
  8.   
  9. _start:  
  10.     jmp     main  
  11.   
  12. clear_screen:               # 清屏函数  
  13.     movb    $0x06,  %ah     # 功能号0x06  
  14.     movb    $0,     %al     # 上卷全部行,即清屏  
  15.     movb    $0,     %ch     # 左上角行  
  16.     movb    $0,     %ch     # 左上角列    
  17.     movb    $24,    %dh     # 右下角行  
  18.     movb    $79,    %dl     # 右下角列  
  19.     movb    $0x07,  %bh     # 空白区域属性  
  20.     int     $0x10  
  21.     ret  
  22.   
  23. main:  
  24.     movw    %cx,    %ax  
  25.     movw    %ax,    %ds  
  26.     movw    %ax,    %es  
  27.   
  28.     call    clear_screen    # 清屏  
  29.   
  30.     # 设置成图形模式,0x6a为800x600, 16种颜色  
  31.     movb    $0,     %ah     # 功能号0x0  
  32.     movb    $0x6a,  %al     # 显示模式  
  33.     int     $0x10  
  34.   
  35.     # 画一条直线  
  36.     movb    $0x0,   %bh     # 视频页  
  37.     movw    $300,   %dx     # y坐标  
  38.     movw    $100,   %cx     # x坐标  
  39.     movb    $0x0c,  %ah     # 功能号  
  40.     movb    $9,     %al     # 像素值(颜色)  
  41. 1:    
  42.     int     $0x10  
  43.     incw    %cx             # 下一个像素  
  44.     cmpw    $700,   %cx     # 是否到了结束位置  
  45.     jne     1b  
  46.   
  47. 1:  
  48.     jmp     1b  
  49.   
  50.     .org    0x1fe,  0x90  
  51.     .word   0xaa55  

结果:


2.图形模式用功能0x13显示字符串

  1. # This program draws text and a straight line in graphics mode.  
  2. # 2012-12-24 20:42  
  3. # guzhoudiaoke@126.com  
  4.   
  5. .section .text  
  6. .global _start  
  7. .code16  
  8.   
  9. _start:  
  10.     jmp     main  
  11.   
  12. clear_screen:               # 清屏函数  
  13.     movb    $0x06,  %ah     # 功能号0x06  
  14.     movb    $0,     %al     # 上卷全部行,即清屏  
  15.     movb    $0,     %ch     # 左上角行  
  16.     movb    $0,     %ch     # 左上角列    
  17.     movb    $24,    %dh     # 右下角行  
  18.     movb    $79,    %dl     # 右下角列  
  19.     movb    $0x07,  %bh     # 空白区域属性  
  20.     int     $0x10  
  21.     ret  
  22.   
  23. main:  
  24.     movw    %cx,    %ax  
  25.     movw    %ax,    %ds  
  26.     movw    %ax,    %es  
  27.   
  28.     call    clear_screen    # 清屏  
  29.   
  30.     # 设置成图形模式,0x6a为800x600, 16种颜色  
  31.     movb    $0,     %ah     # 功能号0x0  
  32.     movb    $0x6a,  %al     # 显示模式  
  33.     int     $0x10  
  34.   
  35.     # 显示文字  
  36.     movw    $msgstr,%ax  
  37.     movw    %ax,    %bp  
  38.     movw    len,    %cx  
  39.     movb    $0x13,  %ah  
  40.     movb    $0,     %al  
  41.     movb    $0x04,  %bl  
  42.     movb    $0x0,   %bh  
  43.     movb    $0x02,  %dh  
  44.     movb    $0x04,  %dl  
  45.     int     $0x10  
  46.   
  47.     # 画一条直线  
  48.     movb    $0x0,   %bh     # 视频页  
  49.     movw    $300,   %dx     # y坐标  
  50.     movw    $100,   %cx     # x坐标  
  51.     movb    $0x0c,  %ah     # 功能号  
  52.     movb    $9,     %al     # 像素值(颜色)  
  53. 1:    
  54.     int     $0x10  
  55.     incw    %cx             # 下一个像素  
  56.     cmpw    $700,   %cx     # 是否到了结束位置  
  57.     jne     1b  
  58.   
  59. 1:  
  60.     jmp     1b  
  61.   
  62. msgstr:  
  63.     .asciz  "line: start(100, 300), end(700, 300)\n"  
  64. len:  
  65.     .int    . - msgstr  
  66.   
  67.     .org    0x1fe,  0x90  
  68.     .word   0xaa55  

结果:


3.内存映射图形

对于内存映射图形视频模式0x13最容易使用。这时屏幕像素映射为一个字节数组,每个像素一个字节。
共有320*200个像素,因为有256种颜色,所以每个像素一个字节。左上角像素对应地址0xa0000。
模式0x13中,每个整数色彩值表示调色板的色彩表的索引。调色板中每个项都由三个独立的整数(0~63)构成,称为RGB值。调色板的第0项控制着屏幕的背景色。
有两个输出端口用于控制视频调色板:送往端口0x3c8的值表示要修改的调色板表项,送往端口0x3c9的是要修改的颜色值。
示例:
  1. # This program draws color pixels at mode 0x13  
  2. # 2012-12-24 21:31  
  3. # guzhoudiaoke@126.com  
  4.   
  5. .section .text  
  6. .global _start  
  7. .code16  
  8.   
  9. _start:  
  10.     jmp     main  
  11.   
  12. #--------------------------------------------------------------  
  13. # 清屏函数:  
  14. #   设置屏幕背景色,调色板的索引0指代的颜色为背景色  
  15. clear_screen:               # 清屏函数  
  16.     movb    $0x06,  %ah     # 功能号0x06  
  17.     movb    $0,     %al     # 上卷全部行,即清屏  
  18.     movb    $0,     %ch     # 左上角行  
  19.     movb    $0,     %ch     # 左上角列    
  20.     movb    $24,    %dh     # 右下角行  
  21.     movb    $79,    %dl     # 右下角列  
  22.     movb    $0x07,  %bh     # 空白区域属性  
  23.     int     $0x10  
  24.     ret  
  25.   
  26. #----------------------------------------------------------------  
  27. # 设置显示模式函数  
  28. set_video_mode:  
  29.     movb    $0,         %ah         # 功能号0x0  
  30.     movb    $MODE_0X13, %al         # 显示模式  
  31.     int     $0x10  
  32.     ret  
  33.   
  34. #---------------------------------------------------------------  
  35. # 显示一些文字函数:  
  36. #   使用INT 0x10中断0x13功能,显示计算机当前工作的显示模式  
  37. draw_some_text:  
  38.     movw    $msg_str,   %bp         # ES:BP为字符串地址  
  39.     movw    msg_len,    %cx         # 显示字符数  
  40.     movb    $0x13,      %ah         # 功能号  
  41.     movb    $0,         %al         # 显示模式  
  42.     movb    $TEXT_COLOR,%bl         # 属性值  
  43.     movb    $0,         %bh         # 视频页  
  44.     movb    $TEXT_ROW,  %dh         # 显示起始行  
  45.     movb    $TEXT_COL,  %dl         # 显示起始列  
  46.     int     $0x10  
  47.   
  48.     ret  
  49.   
  50. #----------------------------------------------------------------  
  51. # 设置背景颜色为深蓝色  
  52. set_screen_bk_color:  
  53.     movw    $VIDEO_PALLETE_PORT,    %dx  
  54.     movb    $PA_INDEX_BACKGROUND,   %al  
  55.     outb    %al,                    %dx  
  56.   
  57.     movw    $COLOR_SELECTION_PORT,  %dx  
  58.     movb    $0,                     %al     # 红  
  59.     outb    %al,                    %dx  
  60.     movb    $0,                     %al     # 绿  
  61.     outb    %al,                    %dx  
  62.     movb    $18,                    %al     # 蓝(亮度18/63)  
  63.     outb    %al,                    %dx  
  64.     ret  
  65.   
  66. #----------------------------------------------------------------  
  67. # 通过写显存绘制一些像素点:  
  68. #   首先设置调色板索引1处的颜色为白色  
  69. #   然后通过写显存的方式,向ES:DI写入数据(PA_INDEX_WHITE)  
  70. draw_some_pixels:  
  71.     # 把索引1处的颜色改为白色(63,63,63)  
  72.     movw    $VIDEO_PALLETE_PORT,    %dx  
  73.     movb    $PA_INDEX_WHITE,        %al  
  74.     outb    %al,                    %dx  
  75.     movw    $COLOR_SELECTION_PORT,  %dx  
  76.     movb    $63,                    %al     # 红  
  77.     outb    %al,                    %dx  
  78.     movb    $63,                    %al     # 绿  
  79.     outb    %al,                    %dx  
  80.     movb    $63,                    %al     # 蓝  
  81.     outb    %al,                    %dx  
  82.   
  83.     # 设置ES的值  
  84.     movw    $VIDEO_SEG_GRAPHIC,     %ax  
  85.     movw    %ax,                    %es  
  86.   
  87.     # 设置要显示的像素位置的显存地址(目的地址)  
  88.     movw    $(PIXEL_ROW_ST*320 + PIXEL_COL_ST), %di  
  89.     movb    $PA_INDEX_WHITE,        %al  
  90.     movw    $PIXEL_COUNT,           %cx  
  91.   
  92. draw_a_pixel:  
  93.     stosb  
  94.     addw    $5,                     %di  
  95.     loop    draw_a_pixel  
  96.   
  97.     ret  
  98.   
  99. main:  
  100.     movw    %cx,    %ax  
  101.     movw    %ax,    %ds  
  102.     movw    %ax,    %es  
  103.   
  104.     call    clear_screen        # 清屏  
  105.     call    set_video_mode      # 设置显示模式  
  106.     call    set_screen_bk_color # 设置背景颜色  
  107.     call    draw_some_text      # 绘制字符串  
  108.     call    draw_some_pixels    # 绘制像素  
  109.   
  110. 1:  
  111.     jmp     1b  
  112.   
  113. # 常量定义:  
  114.     VIDEO_SEG_TEXT      = 0xb800  
  115.     VIDEO_SEG_GRAPHIC   = 0xa000  
  116.   
  117.     VIDEO_PALLETE_PORT  = 0x3c8  
  118.     COLOR_SELECTION_PORT= 0x3c9  
  119.       
  120.     MODE_0X13           = 0x13  
  121.   
  122.     PA_INDEX_BACKGROUND = 0x0  
  123.     PA_INDEX_WHITE      = 0x1  
  124.   
  125.     TEXT_ROW            = 0x01  
  126.     TEXT_COL            = 0x00  
  127.     TEXT_COLOR          = 0x04  
  128.   
  129.     PIXEL_ROW_ST        = 100  
  130.     PIXEL_COL_ST        = 160-5*10  
  131.     PIXEL_COUNT         = 20  
  132.   
  133. msg_str:  
  134. msg_mode:  
  135.     .asciz  "video mode: 0x13"  
  136.     .org    msg_mode+40,        0  
  137. msg_scr_res:  
  138.     .asciz  "screen resolution:320x200"  
  139.     .org    msg_scr_res+40,     0  
  140. msg_color_num:  
  141.     .asciz  "color num:256"  
  142.     .org    msg_color_num+40*4, 0  
  143. msg_babyos:  
  144.     .asciz  "The new Baby OS will have a GUI,but now it can only draw some pixels, haha..And merry Christmas!"  
  145. msg_len:  
  146.     .int    . - msg_str - 1  
  147.   
  148.     .org    0x1fe,  0x90  
  149.     .word   0xaa55  

结果:


注释:

文字是用的BIOS INT 0x10显示的,VGA的0x13模式下显示的文字为40列x25行,字符框8x8,看上去有点丑,以后再研究下超级VGA(SVGA)吧~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值