简介

上一节我们使用C语言绘制了简单的图形界面,实现了汇编语言和C语言共同开发操作系统,只有当C语言力不能逮,特别是需要操作硬件时,才会使用汇编语言。

我们实现图像绘制的办法是,给每一个像素设定指定的数值,这个数值只能位于0-256这个范畴,256种颜色显然是不够用的,而且还不论颜色的亮度,饱和度等这些成分呢。为能够比较好的表示颜色的,一般都使用RGB模式,表示一个RGB颜色需要24位数,便开发了调色板系统。

调色板系统就是把多种RGB颜色的24位数值放入到一个数组中,原来的八位数不再对应一个颜色值,而是变成这个数组的下标,硬件在显示像素颜色时,从像素对应的显存读取这个八位数,然后把这个数当做下标,在RGB颜色素组中找到对应的RGB颜色值,再把这个颜色值显示到对应的像素上。

为了简单起见,我们使用的RGB颜色不对,只有16种,编号0-15,分别为:
0x000000 全黑
0xff0000 亮红
0x00ff00 亮绿
0xffff00 亮黄
0x0000ff 亮蓝
0xff00ff 亮紫
0x00ffff 浅亮
0xffffff 全白
0xc6c6c6 亮灰
0x840000 暗红
0x008400 暗绿
0x848400 暗黄
0x000084 暗蓝
0x840084 暗紫
0x008484 浅暗蓝
0x848484 暗灰

要想使显存系统将颜色的显示模式转换成调色板模式,要给硬件发送命令,只要想发送命令时,给某个指定的端口写入特定数值就可以,硬件接收到命令后,可能会产生一些反馈,这些反馈也会存入某些指定的端口,要想得知反馈,程序只要读取某些端口的数据就可以了。

在汇编语言中,从指定端口读取数据的指令叫in, 假设我们把要读取的端口的编号写入到寄存器dx中,那么指令 in al, dx 就把指定端口的数据读入寄存器al. 如果要想往某个端口中写入数据,假设我们把要写入的端口编号放入dx, 把要写入端口的数据放入寄存器al, 那么指令 out dx, al就可以把数据写入指定端口了。

目标

1、使用汇编编写硬件操作函数供C语言调用
io.s 汇编文件如下:

2、注意:下面的开发环境将切换至Ubuntu环境下实现(由于笔者使用的是Mac 电脑,在编译os.c文件反汇编后始终不能绘制出正确的矩形图案,在百般排查中发现代码没有问题,需要换一个开发平台。工具:clang 编译器、nasm、objconv、VirtualBox。

;io 操作函数定义,给C语言调用
;根据C语言函数调用规则,eax 寄存器作为返回值,edx 在定义的汇编函数中没有保存到栈中;[SECTION .s32]
[BITS 32];实现hlt 功能
;void io_hlt();
io_hlt:hltret;读取指定端口8位数据
;char io_in8(int port);
io_in8:mov edx,[esp+4]mov eax,0in al,dxret ;读取指定端口16位数据
;int io_in16(int port);
io_in16:mov edx,[esp+4]mov eax,0in ax,dxret ;读取指定端口32位数据
;int io_in32(int port);
io_in32:mov edx,[esp+4]in eax,dxret ;指定端口写入8位数据
;void io_out8(int port,char value);
io_out8:mov edx,[esp+4]mov al,[esp+8]out dx,alret ;指定端口写入16位数据
;void io_out16(int port,int value);
io_out16:mov edx,[esp+4]mov ax,[esp+8]out dx,axret ;指定端口写入32位数据
;void io_out32(int port,int value);
io_out32:mov edx,[esp+4]mov eax,[esp+8]out dx,eaxret;关闭cpu可屏蔽中断
;void io_cli();
io_cli:cli ret ;打开cpu可屏蔽中断
;void io_seti();
io_seti:sti  ret;获取程序状态寄存器值
;int io_readFlag();
io_readFlag:pushfd pop eax ret ;设置程序状态寄存器值
;void io_writeFlag(int value);
io_writeFlag:mov edx,[esp+4]push eax popfdret

为了方便C语言调用汇编编写的函数,我们新建一个C语言头文件存放函数声明,方便在*.c 文件中使用汇编函数,io.h 头文件内容如下:

//
//  io.h
//  os-test
//
//  Created by vincent on 2018/10/31.
//  Copyright © 2018年 vincent. All rights reserved.
////实现hlt 功能
extern void io_hlt();//读取指定端口8位数据
extern char io_in8(int port);//读取指定端口16位数据
extern int io_in16(int port);//读取指定端口32位数据
extern int io_in32(int port);//指定端口写入8位数据
extern void io_out8(int port,char value);//指定端口写入16位数据
extern void io_out16(int port,int value);//指定端口写入32位数据
extern void io_out32(int port,int value);//关闭cpu可屏蔽中断
extern void io_cli();//打开cpu可屏蔽中断--在设置调色板时调用开启可屏蔽中断会奔溃
//extern void io_seti();//获取程序状态寄存器值
extern int io_readFlag();//设置程序状态寄存器值
extern void io_writeFlag(int value);

2、使用C语言设置调色板,os.c 文件如下:

#include<stdio.h>
#include "io.h"void initPallet();//操作系统C语言入口函数--可以指定为其他,kernel.s 汇编代码call 需要指定调用
void init_main() {initPallet();for(; ;){io_hlt();}}void initPallet(){//定义调色板static char table_rgb[16*3] = {0x00,  0x00,  0x00,0xff,  0x00,  0x00,0x00,  0xff,  0x00,0xff,  0xff,  0x00,0x00,  0x00,  0xff,0xff,  0x00,  0xff,0x00,  0xff,  0xff,0xff,  0xff,  0xff,0xc6,  0xc6,  0xc6,0x84,  0x00,  0x00,0x00,  0x84,  0x00,0x84,  0x84,  0x00,0x00,  0x00,  0x84,0x84,  0x00,  0x84,0x00,  0x84,  0x84,0x84,  0x84,  0x84,};char *p = table_rgb;int flag = io_readFlag();io_cli();io_out8(0x03c8, 0);for(int i=0;i<16;i++) {io_out8(0x03c9, p[i]);io_out8(0x03c9, p[i+1]);io_out8(0x03c9, p[i+2]);p += 3;}io_writeFlag(flag);p = (char *)0xa0000;for (int i = 0; i <= 0xffff; i++) {*p = i & 0x0f;p++;}}

由于调色板的RGB数组是我们程序设定的,因此就必须要把我们设定的调色板数组的数据传递给硬件显示系统,这样它才能使用我们设定的颜色来描绘每一个像素点。把调色板的数据发送给硬件需要以下操作步骤:
1)关闭中断,防止CPU被干扰
2)将调色板的号码写入端口0x03c8, 由于我们现在只有一个调色板,因此调色板的编号默认为0,如果要设置多个调色板,那么其他调色板的编号可以一次为1,2…等
3) 将RGB的颜色数值依次写入端口0x3c9, 假设我们要写入的RGB颜色值是
0x848484 暗灰
那么在C语言中,要分3次调用io_out8, 例如:
io_out(0x3c9, 0x84);
io_out(0x3c9, 0x84);
io_out(0x3c9, 0x84);

按前面方法编译、修改相关文件,虚拟机加载虚拟软盘文件运行结果如下:

至此,我们的调色板设置完成!

3、有了调色板功能我们再绘制其他图形看看效果,下面的C语言代码将在屏幕上显示几个矩形,修改os.c 文件如下:

// !compile method
// clang -m32 -c os.c -o os.o
// objconv -fnasm os.o -o os.s#include "io.h"//定义调色板颜色
#define  COL8_000000  0
#define  COL8_FF0000  1
#define  COL8_00FF00  2
#define  COL8_FFFF00  3
#define  COL8_0000FF  4
#define  COL8_FF00FF  5
#define  COL8_00FFFF  6
#define  COL8_FFFFFF  7
#define  COL8_C6C6C6  8
#define  COL8_840000  9
#define  COL8_008400  10
#define  COL8_848400  11
#define  COL8_000084  12
#define  COL8_840084  13
#define  COL8_008484  14
#define  COL8_848484  15//屏幕宽度
#define SCREEN_WIDTH 320void initPallet();/***绘制矩形*x             矩形左上角x坐标*y             矩形左上角y坐标*width         宽度*height        高度*colIndex      pallet_color 类型调色板颜色索引,即矩形颜色*/void fillRect(int x,int y,int width,int height,char colIndex);//操作系统C语言入口函数--可以指定为其他
void init_main() {initPallet();fillRect(10, 30, 100,100, COL8_FF0000);fillRect(50, 80, 100, 100, COL8_00FF00);fillRect(100, 110, 100, 100, COL8_0000FF);for(; ;){io_hlt();}}void initPallet(){//定义调色板static char table_rgb[16*3] = {0x00,  0x00,  0x00,0xff,  0x00,  0x00,0x00,  0xff,  0x00,0xff,  0xff,  0x00,0x00,  0x00,  0xff,0xff,  0x00,  0xff,0x00,  0xff,  0xff,0xff,  0xff,  0xff,0xc6,  0xc6,  0xc6,0x84,  0x00,  0x00,0x00,  0x84,  0x00,0x84,  0x84,  0x00,0x00,  0x00,  0x84,0x84,  0x00,  0x84,0x00,  0x84,  0x84,0x84,  0x84,  0x84,};char *rgb = table_rgb;int flag = io_readFlag();io_cli();io_out8(0x03c8, 0);for(int i=0;i<16;i++){io_out8(0x03c9,rgb[0]);io_out8(0x03c9,rgb[1]);io_out8(0x03c9,rgb[2]);rgb += 3;}io_writeFlag(flag);
}void fillRect(int x,int y,int width,int height,char colIndex){char *vram = (char *)0xa0000;for(int i=y;i<=y+height;i++){for(int j=x;j<=x+width;j++){vram[i*SCREEN_WIDTH+j] = colIndex;}}
}

将上面的代码编译、反编译成汇编,去掉相应多余的汇编语句,编译出kernel.bat 后加载执行后效果如下:

使用调色板功能实现矩形的绘制成功完成!

4、绘制桌面背景
修改os.c 文件如下绘制桌面背景:

// !compile method
// clang -m32 -c os.c -o os.o
// objconv -fnasm os.o -o os.s#include "io.h"//定义调色板颜色
#define  COL8_000000  0
#define  COL8_FF0000  1
#define  COL8_00FF00  2
#define  COL8_FFFF00  3
#define  COL8_0000FF  4
#define  COL8_FF00FF  5
#define  COL8_00FFFF  6
#define  COL8_FFFFFF  7
#define  COL8_C6C6C6  8
#define  COL8_840000  9
#define  COL8_008400  10
#define  COL8_848400  11
#define  COL8_000084  12
#define  COL8_840084  13
#define  COL8_008484  14
#define  COL8_848484  15//屏幕宽度
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 200void initPallet();/***绘制矩形*x             矩形左上角x坐标*y             矩形左上角y坐标*width         宽度*height        高度*colIndex      pallet_color 类型调色板颜色索引,即矩形颜色*/void fillRect(int x,int y,int width,int height,char colIndex);//操作系统C语言入口函数--可以指定为其他
void init_main() {initPallet();fillRect(0,0,SCREEN_WIDTH-1,SCREEN_HEIGHT-29, COL8_008484);fillRect(0,SCREEN_HEIGHT-28,SCREEN_WIDTH-1,28, COL8_848484);fillRect(0,SCREEN_HEIGHT-27,SCREEN_WIDTH,1, COL8_848484);fillRect(0,SCREEN_HEIGHT-26,SCREEN_WIDTH,25, COL8_C6C6C6);fillRect(3,SCREEN_HEIGHT-24,56,1, COL8_FFFFFF);fillRect(2,SCREEN_HEIGHT-24,1,20, COL8_FFFFFF);fillRect(3,SCREEN_HEIGHT-4,56,1, COL8_848484);fillRect(59,SCREEN_HEIGHT-23,1,19, COL8_848484);fillRect(2,SCREEN_HEIGHT-3,57,0, COL8_000000);fillRect(60,SCREEN_HEIGHT-24,0,19, COL8_000000);fillRect(SCREEN_WIDTH-47,SCREEN_HEIGHT-24,43,1, COL8_848484);fillRect(SCREEN_WIDTH-47,SCREEN_HEIGHT-23,0,19, COL8_848484);fillRect(SCREEN_WIDTH-47,SCREEN_HEIGHT-3,43,0, COL8_FFFFFF);fillRect(SCREEN_WIDTH-3,SCREEN_HEIGHT-24,0,21, COL8_FFFFFF);for(; ;){io_hlt();}}void initPallet(){//定义调色板static unsigned char table_rgb[16*3] = {0x00,  0x00,  0x00,0xff,  0x00,  0x00,0x00,  0xff,  0x00,0xff,  0xff,  0x00,0x00,  0x00,  0xff,0xff,  0x00,  0xff,0x00,  0xff,  0xff,0xff,  0xff,  0xff,0xc6,  0xc6,  0xc6,0x84,  0x00,  0x00,0x00,  0x84,  0x00,0x84,  0x84,  0x00,0x00,  0x00,  0x84,0x84,  0x00,  0x84,0x00,  0x84,  0x84,0x84,  0x84,  0x84,};unsigned char *rgb = table_rgb;int flag = io_readFlag();io_cli();io_out8(0x03c8, 0);for(int i=0;i<16;i++){io_out8(0x03c9,rgb[0] / 4);io_out8(0x03c9,rgb[1] / 4);io_out8(0x03c9,rgb[2] / 4);rgb += 3;}io_writeFlag(flag);
}void fillRect(int x,int y,int width,int height,char colIndex){char *vram = (char *)0xa0000;for(int i=y;i<=y+height;i++){for(int j=x;j<=x+width;j++){vram[i*SCREEN_WIDTH+j] = colIndex;}}
}

加载虚拟软盘文件运行如下:

至此绘制的背景桌面已经基本出来了!

09.调色板绘制系统界面相关推荐

  1. 使用调色板绘制系统界面

    相关代码可视频可在网易云课堂下载: Linux kernel Hacker, 从零构建自己的内核 上一节,我们已经可以使用C语言实现图像绘制,但操作系统的用户界面不可能是那种扎眼的条纹图案,这一节,我 ...

  2. 30天自制操作系统 pdf_30天自制操作系统:第四天:系统界面绘制

    第四天: OUT:让cpu给设备发送电信号. IN:让cpu从设备获取电信号. 为了区别不同的设备,要使用设备号码,用port表示. pushad: 将所有的32位通用寄存器压入堆栈 pusha:将所 ...

  3. matlab系统的根轨迹,实验五 利用MATLAB绘制系统根轨迹

    <实验五 利用MATLAB绘制系统根轨迹>由会员分享,可在线阅读,更多相关<实验五 利用MATLAB绘制系统根轨迹(6页珍藏版)>请在人人文库网上搜索. 1.实验五 利用MAT ...

  4. 在Matlab中绘制系统的根轨迹图

    在Matlab中绘制系统的根轨迹图 例如某系统的开环传递函数为: 通过上面的开环传递函数可以直接求出2个开环共轭复零点,以及5个开环极点,然后确定根轨迹分支数-自己画根轨迹图的话还是比较麻烦的,这么简 ...

  5. 鸿蒙系统平板界面,首发预装鸿蒙OS!华为MatePad Pro 2系统界面曝光

    首发预装鸿蒙OS!华为MatePad Pro 2系统界面曝光 2021-04-04 23:09:10 43点赞 33收藏 50评论 前段时间,华为官方已正式宣布将在本月正式推出鸿蒙OS系统正式版,并将 ...

  6. 基于QT简易智能家居系统界面设计

    简易版智能家居系统界面,登录窗口.控制面板.及两者间的逻辑关系 请点击:相关代码 设计登录界面 这里采用ui绘制+信号槽函数实现逻辑功能,绘制方面用到Label.Widge.Line Edit.Pus ...

  7. 江阴工控机服务器维修,西门子工控机上电进不了系统界面维修

    西门子工控机上电进不了系统界面维修,西门子工控机快速修复故障:开不了机维修,屏幕不亮维修,白屏维修, 黑屏维修,按键失灵维修,触摸失灵维修,触摸不灵维修,花屏维修,进不了系统维修,系统死机维修,程序丢 ...

  8. 华为鸿蒙系统界面_谷歌懵圈!华为鸿蒙系统界面首次曝光,网友纷纷表示支持...

    谷歌懵圈!华为鸿蒙系统界面首次曝光,网友纷纷表示支持 最近的科技圈被华为禁令的消息刷屏,甚至已经上升到人尽皆知的地步,制裁华为的禁令诱发一连串的连锁效应.大量海外供应商集体宣布断供,而就连和华为合作已 ...

  9. 绘制分类界面以及性能曲面中的meshgrid函数

    简 介: 本文讨论了meshgrid产生的三种方法,特别从meshgrid 到点阵列表之间的转换关系. 关键词: meshgrid,mgrid #mermaid-svg-6JtzvULJCZcohnG ...

最新文章

  1. 数据蒋堂 | JOIN延伸 - 维度概念
  2. 是你的数据还不够强!谷歌大脑「数据增强」开源,大神QuocLe出品
  3. Java内存访问重排序的研究
  4. python面向对象(2)—— 继承(2)
  5. 一文理清Http2.0
  6. BGP——同步功能【Synchronization】【路由黑洞】
  7. 如何强制修改vivado工程打开版本
  8. 读《自己动手写操作系统》
  9. ServletContext的用法
  10. 大数据技术之大数据概论
  11. Google Chrome 怎么下载离线安装包
  12. 微信活码系统源码/微信群二维码/活码生成网站系统/生成微信活码
  13. Holt两参数指数平滑法的R实现
  14. 【转载】联想ThinkPad X390笔记本装win7系统及BIOS设置方法
  15. 成功的交易者有什么好的方法去做期货交易
  16. Autogrid5划分网格
  17. UE4 安装及入门项目
  18. FPGA-基于UART的QVGA显示(一)(实现PC端发送字母数字汉字的分别显示)
  19. python数据分析:使用statsmodels构建价格需求弹性模型
  20. cad无法加载arx文件_CAD文件无法打开,这两点原因你必须要知道

热门文章

  1. IP2188中文数据手册
  2. 安卓手机扫二维码从FTP服务器下载apk
  3. CTF-NEFU校赛-题解
  4. 前端设计人员必会技能 - gif动画图片制作
  5. RDKit | 建立溶解度预测的LightGBM回归模型
  6. 【Java八股文之基础篇(十九)】函数式编程之Stream流(上)
  7. Python语言程序设计基础 第二版(嵩天著)课后答案第六章
  8. 浙江从小学生就上计算机课,浙江省2012年1月自学考试小学数学教学研究试题
  9. 浅析支付宝钱包支付流程
  10. 少儿Python编程6-计算机数据结构和算法