babyos (二)——使用BIOS以及直接写显存绘制图形
2012-12-25 02:00
337 查看
注:以下程序系由相应的Intel格式汇编改编而来,略有修改,若发现bug,欢迎指正。若有问题,欢迎交流。若能帮助一二访客,幸甚。
一年前仿照Skelix 写过一个简单的内核,并命名为BabyOS。当时代码大部分用的Skelix的,终究有些遗憾,所以想趁今年寒假--工作前最后一个假期,重新实现一下BabyOS,力求尽量用自己的代码实现。所以前几天学习了一下AT&T 汇编、内联汇编及C与汇编的相互调用。下一个问题就是显示,经过许多考虑,这次准备尝试一下图形界面的系统(因为看上去更有趣些),或许有点舍本求末的嫌疑,但我写个OS kernel主要是好玩,从未想有正式应用,所以怎么好玩就怎么来。
昨晚研究了下BIOS INT 0x10显示字符,今晚决定不管有用没有先学习一下BIOS INT 0x10及实模式下写显存来显示图形的知识。
示例,画线程序:
结果:
结果:
共有320*200个像素,因为有256种颜色,所以每个像素一个字节。左上角像素对应地址0xa0000。
模式0x13中,每个整数色彩值表示调色板的色彩表的索引。调色板中每个项都由三个独立的整数(0~63)构成,称为RGB值。调色板的第0项控制着屏幕的背景色。
有两个输出端口用于控制视频调色板:送往端口0x3c8的值表示要修改的调色板表项,送往端口0x3c9的是要修改的颜色值。
示例:
结果:
注释:
文字是用的BIOS INT 0x10显示的,VGA的0x13模式下显示的文字为40列x25行,字符框8x8,看上去有点丑,以后再研究下超级VGA(SVGA)吧~
一年前仿照Skelix 写过一个简单的内核,并命名为BabyOS。当时代码大部分用的Skelix的,终究有些遗憾,所以想趁今年寒假--工作前最后一个假期,重新实现一下BabyOS,力求尽量用自己的代码实现。所以前几天学习了一下AT&T 汇编、内联汇编及C与汇编的相互调用。下一个问题就是显示,经过许多考虑,这次准备尝试一下图形界面的系统(因为看上去更有趣些),或许有点舍本求末的嫌疑,但我写个OS kernel主要是好玩,从未想有正式应用,所以怎么好玩就怎么来。
昨晚研究了下BIOS INT 0x10显示字符,今晚决定不管有用没有先学习一下BIOS INT 0x10及实模式下写显存来显示图形的知识。
1.绘制像素
----------------------------------------------------------------------- INT 0x10可识别的视频图形模式 -------------------------------------------------------------------- 模式 分辨率(列*行,像素) 颜色数 6 640x200 2 0DH 320x200 16 0EH 640x350 16 0FH 640x350 2 10H 640x200 16 11H 640x480 2 12H 640x480 16 13H 320x200 256 6AH 800x600 16 -----------------------------------------------------------------------当视频控制器处于图形模式时,INT 0x10的功能0CH在屏幕上绘制一个像素点。(功能0CH执行的相当慢)
----------------------------------------------------------------------- INT 0x10 功能0CH --------------------------------------------------------------- 描述: 写像素 接受参数: AH 0CH AL 像素值 BH 视频页 CX X坐标 DX Y坐标 返回值: 无 注意: 视频显示必须处于图形模式下。像素值的范围和坐标范围与当前的图形模式有关。 如果AL的位7置位,新的像素同当前像素的内容进行异或运算。 -------------------------------------------------------------------------
示例,画线程序:
# This program draws a straight line in graphics mode. # 2012-12-24 20:42 # guzhoudiaoke@126.com .section .text .global _start .code16 _start: jmp main 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 main: movw %cx, %ax movw %ax, %ds movw %ax, %es call clear_screen # 清屏 # 设置成图形模式,0x6a为800x600, 16种颜色 movb $0, %ah # 功能号0x0 movb $0x6a, %al # 显示模式 int $0x10 # 画一条直线 movb $0x0, %bh # 视频页 movw $300, %dx # y坐标 movw $100, %cx # x坐标 movb $0x0c, %ah # 功能号 movb $9, %al # 像素值(颜色) 1: int $0x10 incw %cx # 下一个像素 cmpw $700, %cx # 是否到了结束位置 jne 1b 1: jmp 1b .org 0x1fe, 0x90 .word 0xaa55
结果:
2.图形模式用功能0x13显示字符串
# This program draws text and a straight line in graphics mode. # 2012-12-24 20:42 # guzhoudiaoke@126.com .section .text .global _start .code16 _start: jmp main 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 main: movw %cx, %ax movw %ax, %ds movw %ax, %es call clear_screen # 清屏 # 设置成图形模式,0x6a为800x600, 16种颜色 movb $0, %ah # 功能号0x0 movb $0x6a, %al # 显示模式 int $0x10 # 显示文字 movw $msgstr,%ax movw %ax, %bp movw len, %cx movb $0x13, %ah movb $0, %al movb $0x04, %bl movb $0x0, %bh movb $0x02, %dh movb $0x04, %dl int $0x10 # 画一条直线 movb $0x0, %bh # 视频页 movw $300, %dx # y坐标 movw $100, %cx # x坐标 movb $0x0c, %ah # 功能号 movb $9, %al # 像素值(颜色) 1: int $0x10 incw %cx # 下一个像素 cmpw $700, %cx # 是否到了结束位置 jne 1b 1: jmp 1b msgstr: .asciz "line: start(100, 300), end(700, 300)\n" len: .int . - msgstr .org 0x1fe, 0x90 .word 0xaa55
结果:
3.内存映射图形
对于内存映射图形视频模式0x13最容易使用。这时屏幕像素映射为一个字节数组,每个像素一个字节。共有320*200个像素,因为有256种颜色,所以每个像素一个字节。左上角像素对应地址0xa0000。
模式0x13中,每个整数色彩值表示调色板的色彩表的索引。调色板中每个项都由三个独立的整数(0~63)构成,称为RGB值。调色板的第0项控制着屏幕的背景色。
有两个输出端口用于控制视频调色板:送往端口0x3c8的值表示要修改的调色板表项,送往端口0x3c9的是要修改的颜色值。
示例:
# This program draws color pixels at mode 0x13 # 2012-12-24 21:31 # guzhoudiaoke@126.com .section .text .global _start .code16 _start: jmp main #-------------------------------------------------------------- # 清屏函数: # 设置屏幕背景色,调色板的索引0指代的颜色为背景色 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 #---------------------------------------------------------------- # 设置显示模式函数 set_video_mode: movb $0, %ah # 功能号0x0 movb $MODE_0X13, %al # 显示模式 int $0x10 ret #--------------------------------------------------------------- # 显示一些文字函数: # 使用INT 0x10中断0x13功能,显示计算机当前工作的显示模式 draw_some_text: movw $msg_str, %bp # ES:BP为字符串地址 movw msg_len, %cx # 显示字符数 movb $0x13, %ah # 功能号 movb $0, %al # 显示模式 movb $TEXT_COLOR,%bl # 属性值 movb $0, %bh # 视频页 movb $TEXT_ROW, %dh # 显示起始行 movb $TEXT_COL, %dl # 显示起始列 int $0x10 ret #---------------------------------------------------------------- # 设置背景颜色为深蓝色 set_screen_bk_color: movw $VIDEO_PALLETE_PORT, %dx movb $PA_INDEX_BACKGROUND, %al outb %al, %dx movw $COLOR_SELECTION_PORT, %dx movb $0, %al # 红 outb %al, %dx movb $0, %al # 绿 outb %al, %dx movb $18, %al # 蓝(亮度18/63) outb %al, %dx ret #---------------------------------------------------------------- # 通过写显存绘制一些像素点: # 首先设置调色板索引1处的颜色为白色 # 然后通过写显存的方式,向ES:DI写入数据(PA_INDEX_WHITE) draw_some_pixels: # 把索引1处的颜色改为白色(63,63,63) movw $VIDEO_PALLETE_PORT, %dx movb $PA_INDEX_WHITE, %al outb %al, %dx movw $COLOR_SELECTION_PORT, %dx movb $63, %al # 红 outb %al, %dx movb $63, %al # 绿 outb %al, %dx movb $63, %al # 蓝 outb %al, %dx # 设置ES的值 movw $VIDEO_SEG_GRAPHIC, %ax movw %ax, %es # 设置要显示的像素位置的显存地址(目的地址) movw $(PIXEL_ROW_ST*320 + PIXEL_COL_ST), %di movb $PA_INDEX_WHITE, %al movw $PIXEL_COUNT, %cx draw_a_pixel: stosb addw $5, %di loop draw_a_pixel ret main: movw %cx, %ax movw %ax, %ds movw %ax, %es call clear_screen # 清屏 call set_video_mode # 设置显示模式 call set_screen_bk_color # 设置背景颜色 call draw_some_text # 绘制字符串 call draw_some_pixels # 绘制像素 1: jmp 1b # 常量定义: VIDEO_SEG_TEXT = 0xb800 VIDEO_SEG_GRAPHIC = 0xa000 VIDEO_PALLETE_PORT = 0x3c8 COLOR_SELECTION_PORT= 0x3c9 MODE_0X13 = 0x13 PA_INDEX_BACKGROUND = 0x0 PA_INDEX_WHITE = 0x1 TEXT_ROW = 0x01 TEXT_COL = 0x00 TEXT_COLOR = 0x04 PIXEL_ROW_ST = 100 PIXEL_COL_ST = 160-5*10 PIXEL_COUNT = 20 msg_str: msg_mode: .asciz "video mode: 0x13" .org msg_mode+40, 0 msg_scr_res: .asciz "screen resolution:320x200" .org msg_scr_res+40, 0 msg_color_num: .asciz "color num:256" .org msg_color_num+40*4, 0 msg_babyos: .asciz "The new Baby OS will have a GUI,but now it can only draw some pixels, haha..And merry Christmas!" msg_len: .int . - msg_str - 1 .org 0x1fe, 0x90 .word 0xaa55
结果:
注释:
文字是用的BIOS INT 0x10显示的,VGA的0x13模式下显示的文字为40列x25行,字符框8x8,看上去有点丑,以后再研究下超级VGA(SVGA)吧~
相关文章推荐
- 使用BIOS以及直接写显存绘制图形
- 使用原生JavaScript的Canvas实现拖拽式图形绘制,支持画笔、线条、箭头、三角形、矩形、平行四边形、梯形以及多边形和圆形,不依赖任何库和插件,有演示demo
- OpenGL8-直接分配显存-极速绘制(2)
- VS2010 使用TeeChart绘图控件 - 之二 - 绘制图形(折线图,柱状图)
- 用python绘制图形的一些使用技巧
- 使用MFC进行编程,绘制直线椭圆以及样条曲线
- VS2010 MFC使用TeeChart绘图控件之二:绘制图形(折线图,柱状图)
- 使用System.Drawing命名空间绘制图形
- Python:使用pycha快速绘制办公常用图(饼图、垂直直方图、水平直方图、散点图等七种图形)
- android游戏开发框架libgdx的使用(二)--图形绘制
- OpenGL4.x学习之使用着色器、绑定VAO以及绘制最简单的图元——点
- js自定义方法直接申明式的使用以及在jquery的$(function(){})中使用的区别
- 【Android游戏开发之一】:设置全屏以及简单的图形绘制
- 2017_09_02-结构化图形绘制软件GraphViz的使用
- 绘制几何图形——使用android.graphics类
- HTML5之SVG 2D入门2—图形绘制(基本形状)介绍及使用
- Android中View绘制不同状态背景图片原理深入分析以及StateListDrawable使用详解
- 使用gd2绘制基本图形
- 开始使用SmartDraw绘制开发中的各种图形
- HTML5之Canvas绘图——使用Canvas绘制图形的基本教程