目录


获取源码关注公众号《猿小龙》

1.用C语言实现内存写入(harib01a)



C语言中如果使用了write_mem8函数,就会跳转到_write_mem8,此时参数指定的数字就存放在内存里,分别是:

我们想要取得参数指定的数字0x1234或者0x56内容,只需要用MOV指令读入寄存器即可。


naskfunc.nas代码

; naskfunc
; TAB=4 [FORMAT "WCOFF"] ; 制作目标文件的模式
[INSTRSET "i486p"] ; 使用到486为止的指令
[BITS 32] ; 3制作32位模式用的机器语言
[FILE "naskfunc.nas"] ; 文件名 GLOBAL _io_hlt, _io_cli, _io_sti, _io_stihlt
GLOBAL _io_in8, _io_in16, _io_in32
GLOBAL _io_out8, _io_out16, _io_out32
GLOBAL _io_load_eflags, _io_store_eflags [SECTION .text] _io_hlt: ; void io_hlt(void);
HLT
RET _io_cli: ; void io_cli(void);
CLI
RET _io_sti: ; void io_sti(void);
STI
RET _io_stihlt: ; void io_stihlt(void);
STI
HLT
RET _io_in8: ; int io_in8(int port);
MOV EDX,[ESP+4] ; port
MOV EAX,0
IN AL,DX
RET _io_in16: ; int io_in16(int port);
MOV EDX,[ESP+4] ; port
MOV EAX,0
IN AX,DX
RET _io_in32: ; int io_in32(int port);
MOV EDX,[ESP+4] ; port
IN EAX,DX
RET _io_out8: ; void io_out8(int port, int data);
MOV EDX,[ESP+4] ; port
MOV AL,[ESP+8] ; data
OUT DX,AL
RET _io_out16: ; void io_out16(int port, int data);
MOV EDX,[ESP+4] ; port
MOV EAX,[ESP+8] ; data
OUT DX,AX
RET _io_out32: ; void io_out32(int port, int data);
MOV EDX,[ESP+4] ; port
MOV EAX,[ESP+8] ; data
OUT DX,EAX
RET _io_load_eflags: ; int io_load_eflags(void);
PUSHFD ; PUSH EFLAGS
POP EAX
RET _io_store_eflags: ; void io_store_eflags(int eflags);
MOV EAX,[ESP+4]
PUSH EAX
POPFD ; POP EFLAGS
RET

下面修改C语言,这次导入变量

bootpack.c代码

void io_hlt(void);
void io_cli(void);
void io_out8(int port, int data);
int io_load_eflags(void);
void io_store_eflags(int eflags); void init_palette(void);
void set_palette(int start, int end, unsigned char *rgb);
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1); #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 void HariMain(void)
{
char *vram;/* 声明变量vram、用于BYTE [...]地址 */
int xsize, ysize; init_palette();/* 设定调色板 */
vram = (char *) 0xa0000;/* 地址变量赋值 */
xsize = 320;
ysize = 200; /* 根据 0xa0000 + x + y * 320 计算坐标 8*/
boxfill8(vram, xsize, COL8_008484, 0, 0, xsize - 1, ysize - 29);
boxfill8(vram, xsize, COL8_C6C6C6, 0, ysize - 28, xsize - 1, ysize - 28);
boxfill8(vram, xsize, COL8_FFFFFF, 0, ysize - 27, xsize - 1, ysize - 27);
boxfill8(vram, xsize, COL8_C6C6C6, 0, ysize - 26, xsize - 1, ysize - 1); boxfill8(vram, xsize, COL8_FFFFFF, 3, ysize - 24, 59, ysize - 24);
boxfill8(vram, xsize, COL8_FFFFFF, 2, ysize - 24, 2, ysize - 4);
boxfill8(vram, xsize, COL8_848484, 3, ysize - 4, 59, ysize - 4);
boxfill8(vram, xsize, COL8_848484, 59, ysize - 23, 59, ysize - 5);
boxfill8(vram, xsize, COL8_000000, 2, ysize - 3, 59, ysize - 3);
boxfill8(vram, xsize, COL8_000000, 60, ysize - 24, 60, ysize - 3); boxfill8(vram, xsize, COL8_848484, xsize - 47, ysize - 24, xsize - 4, ysize - 24);
boxfill8(vram, xsize, COL8_848484, xsize - 47, ysize - 23, xsize - 47, ysize - 4);
boxfill8(vram, xsize, COL8_FFFFFF, xsize - 47, ysize - 3, xsize - 4, ysize - 3);
boxfill8(vram, xsize, COL8_FFFFFF, xsize - 3, ysize - 24, xsize - 3, ysize - 3); for (;;) {
io_hlt();
}
} void init_palette(void)
{
static unsigned char table_rgb[16 * 3] = {
0x00, 0x00, 0x00, /* 0:黑 */
0xff, 0x00, 0x00, /* 1:梁红 */
0x00, 0xff, 0x00, /* 2:亮绿 */
0xff, 0xff, 0x00, /* 3:亮黄 */
0x00, 0x00, 0xff, /* 4:亮蓝 */
0xff, 0x00, 0xff, /* 5:亮紫 */
0x00, 0xff, 0xff, /* 6:浅亮蓝 */
0xff, 0xff, 0xff, /* 7:白 */
0xc6, 0xc6, 0xc6, /* 8:亮灰 */
0x84, 0x00, 0x00, /* 9:暗红 */
0x00, 0x84, 0x00, /* 10:暗绿 */
0x84, 0x84, 0x00, /* 11:暗黄 */
0x00, 0x00, 0x84, /* 12:暗青 */
0x84, 0x00, 0x84, /* 13:暗紫 */
0x00, 0x84, 0x84, /* 14:浅暗蓝 */
0x84, 0x84, 0x84 /* 15:暗灰 */
};
set_palette(0, 15, table_rgb);
return; /* C语言中的static char语句只能用于数据,相当于汇编中的DB指令 */
} void set_palette(int start, int end, unsigned char *rgb)
{
int i, eflags;
eflags = io_load_eflags(); /* 记录中断许可标志的值 */
io_cli(); /* 将中断许可标志置为0,禁止中断 */
io_out8(0x03c8, start);
for (i = start; i <= end; i++) {
io_out8(0x03c9, rgb[0] / 4);
io_out8(0x03c9, rgb[1] / 4);
io_out8(0x03c9, rgb[2] / 4);
rgb += 3;
}
io_store_eflags(eflags); /* 复原中断许可标志 */
return;
} void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
{
int x, y;
for (y = y0; y <= y1; y++) {
for (x = x0; x <= x1; x++)
vram[y * xsize + x] = c;
}
return;
}

原来书籍中代码较为简单运行后是白屏,没有参考价值,修改代码如上
下面执行make run或者make install为白屏

2.条纹图案(harib01b)

改动上述代码

CPU采用数值运算时,将会进行加减乘除,重要的是计算结果。而对图像进行处理时,更重要的是0和1的排列顺序,经常需要进行反转操作,如下



3.挑战指针(harib01c)



接下来运行





4.指针应用(1)(harib01d)

5.指针应用(2)(harib01e)

6.色号设定(harib01f)

以下色号足够了

相关代码前面已经说明了。

总结一下
下面介绍标志寄存器


接下来说naskfunc.nas

; naskfunc
; TAB=4 [FORMAT "WCOFF"] ; 制作目标文件的模式
[INSTRSET "i486p"] ; 使用到486为止的指令
[BITS 32] ; 3制作32位模式用的机器语言
[FILE "naskfunc.nas"] ; 文件名 GLOBAL _io_hlt, _io_cli, _io_sti, _io_stihlt
GLOBAL _io_in8, _io_in16, _io_in32
GLOBAL _io_out8, _io_out16, _io_out32
GLOBAL _io_load_eflags, _io_store_eflags [SECTION .text] _io_hlt: ; void io_hlt(void);
HLT
RET _io_cli: ; void io_cli(void);
CLI
RET _io_sti: ; void io_sti(void);
STI
RET _io_stihlt: ; void io_stihlt(void);
STI
HLT
RET _io_in8: ; int io_in8(int port);
MOV EDX,[ESP+4] ; port
MOV EAX,0
IN AL,DX
RET _io_in16: ; int io_in16(int port);
MOV EDX,[ESP+4] ; port
MOV EAX,0
IN AX,DX
RET _io_in32: ; int io_in32(int port);
MOV EDX,[ESP+4] ; port
IN EAX,DX
RET _io_out8: ; void io_out8(int port, int data);
MOV EDX,[ESP+4] ; port
MOV AL,[ESP+8] ; data
OUT DX,AL
RET _io_out16: ; void io_out16(int port, int data);
MOV EDX,[ESP+4] ; port
MOV EAX,[ESP+8] ; data
OUT DX,AX
RET _io_out32: ; void io_out32(int port, int data);
MOV EDX,[ESP+4] ; port
MOV EAX,[ESP+8] ; data
OUT DX,EAX
RET _io_load_eflags: ; int io_load_eflags(void);
PUSHFD ; PUSH EFLAGS
POP EAX
RET _io_store_eflags: ; void io_store_eflags(int eflags);
MOV EAX,[ESP+4]
PUSH EAX
POPFD ; POP EFLAGS
RET




运行

7.绘制矩形(harib01g)


8.今天成果(harib01h)

 

挑战30天写操作系统-day4-C语言与画面显示的练习的更多相关文章

  1. 挑战30天写操作系统-day2-汇编语言学习与Makefile入门

    1.介绍文本编辑器 这里,我们直接采用自己windows电脑自带的文本编辑器即可以完成制作要求 2.继续开发 下面先是对昨天使用的helloos.nas文件内容进行详细解释 ; hello-os ; ...

  2. 挑战30天写操作系统-day1-从计算机结构到汇编程序入门

    先动手操作 软盘映像文件制作:先采用二进制编辑器编辑我们所需要的映像文件helloos.img 二进制编辑器下载链接:Bz - c.mos (vcraft.jp) 制作好之后,可以选择写入软盘,通过软 ...

  3. 挑战30天写操作系统-day3-进入32位模式并导入C语言

    目录 1.制作真正的IPL IPL:启动区,启动程序装载器完整代码: ; haribote-ipl ; TAB=4 CYLS EQU 10 ; 声明CYLS=10 ORG 0x7c00 ; 指明程序装 ...

  4. 《30天自制操作系统》笔记(02)——导入C语言

    <30天自制操作系统>笔记(02)——导入C语言 进度回顾 在上一篇,记录了计算机开机时加载IPL程序(initial program loader,一个nas汇编程序)的情况,包括IPL ...

  5. 30天自制操作系统(三)进入32位模式并导入C语言

    1 制作真正的IPL IPL(Initial Program Loader),启动程序装载器,但是之前并没有实质性的装载任何程序,这次作者要开始装载程序了. 虽然现在开发的操作系统啥功能也没有,作者说 ...

  6. 《30天自制操作系统》笔记(06)——CPU的32位模式

    <30天自制操作系统>笔记(06)——CPU的32位模式 进度回顾 上一篇中实现了启用鼠标.键盘的功能.屏幕上会显示出用户按键.点击鼠标的情况.这是通过设置硬件的中断函数实现的,可以说硬件 ...

  7. 30天自制操作系统第九天学习笔记(u盘软盘双启动版本)

    暑假学习小日本的那本书:30天自制操作系统 qq交流群:122358078    ,更多学习中的问题.资料,群里分享 environment:开发环境:ubuntu 第九天的课程已学完,确实有点不想写 ...

  8. 【操作系统】C语言编写的FAT16文件系统

    [操作系统]C语言编写的FAT16文件系统 这是操作系统的期末课程设计作业之一,主要功能是在物理内存中虚拟出一个1M大小的FAT16的文件系统,然后把它读入内存中,进行具体的文件操作,具体的实用性不大 ...

  9. 《30天自制操作系统》笔记(01)——hello bitzhuwei’s OS!【转】

    转自:http://www.cnblogs.com/bitzhuwei/p/OS-in-30-days-01-hello-bitzhuwei-OS.html 阅读目录(Content) 最初的OS代码 ...

随机推荐

  1. Mybaitis入门基础(一)MyBatis的概念引入及工作原理

    阅读目录 一:对原生态JDBC问题的总结 二:MyBatis框架 三:mybatis入门程序 四:mybatis和Hibernate的本质区别与应用场景 五:小结 一:框架前言的那些事 良将难求 胜铁 ...

  2. Java基础语法Day_06(面相对象和封装)

    第1节 描述类介绍与使用 day06_01_面向对象思想的概述 day06_02_面向对象思想的举例 day06_03_类和对象的关系 day06_04_类的定义 day06_05_对象的创建及其使用 ...

  3. js 前端实现下拉刷新 上拉加载

    效果 css html,body{ height:100%; // 其他界面未设置html 无法监听scroll } /* 下拉刷新 */ .refresh-loading { transition: ...

  4. [STL] set 集合

    可以用 if ( a.find(x) == a.end() ) 判断 x 在 a 中是否存在

  5. [笔记] prufer 序列

    什么是 prufer 序列 是可以和 \(n\) 个有标号节点的无根树一一对应的长度为 \(n-2\) 的序列. 一般来说是用于和树相关的组合计数问题,但是可能会出现一些变形,所以除了要了解一些性质, ...

  6. RabbitMQ 3.9( 基础 )

    1.认识MQ 1.1.什么是MQ? MQ全称:message queue 即 消息队列 这个队列遵循的原则:FIFO 即 先进先出 队列里面存的就是message 1.2.为什么要用MQ? 1.2.1 ...

  7. 用 Python 为接口测试自动生成用例

    用Python为接口自动生成测试用例 基于属性的测试会产生大量的.随机的参数,特别适合为单元测试和接口测试生成测试用例 尽管早在2006年haskell语言就有了QuickCheck来进行" ...

  8. a commponent required a bean of type XXXXXX that could not be found-2022新项目

    一.问题由来 目前刚入职一家新公司不久,公司的新项目采用DDD驱动领域设计来进行开发,架构这一块使用的是阿里巴巴开源的最新框架COLA4.0的架构. 主要是这个框架里面的分层设计.主要分为四层:ada ...

  9. uniapp中IOS安卓热更新和整包更新app更新

    在App.vue中 onLaunch: function() { console.log('App Launch'); // #ifdef APP-PLUS this.getVersion(); // ...

  10. Redis设计与实现2.2:数据持久化

    数据持久化 这是<Redis设计与实现>系列的文章,系列导航:Redis设计与实现笔记 RDB持久化 RDB 持久化功能所生成的 RDB 文件是一个经过压缩的二进制文件,通过该文件可以还原 ...