自制操作系统日记(6):静态桌面初步
创始人
2024-01-22 13:25:16
0

代码仓库地址:https://github.com/freedom-xiao007/operating-system

简介

在上篇中我们成功的加载跳转执行了C语言的代码,本篇中将跟随书籍,初步展示了一个系统页面的初步界面,看到桌面那刻还是有点意思的

最终结果展示

不多啰嗦,这里先直接展示结果,最终的运行界面如下:

在这里插入图片描述

可以看到有点模样了,令人激动啊。当最终到这一步的时候,心里开心极了,哈哈

相关代码说明

本篇中的代码修改基本上是抄《30天自制操作系统》中的,但可能是nask和nasm的区别问题,我们需要单独修改的地方也不少,下面我们详细说明下需要修改的地方

setup.asm文件修改

这个文件需要添加界面相关的参数设置,我们将其插入到start的下面,如下:

start:; 画面モードを設定MOV		AL,0x13			; VGA显卡,320x200x8bitMOV		AH,0x00INT		0x10MOV		BYTE [VMODE],8	; 屏幕的模式(参考C语言的引用)MOV		WORD [SCRNX],320MOV		WORD [SCRNY],200MOV		DWORD [VRAM],0x000a0000

func.asm文件修改

这次新增了比较多的函数,但不复杂,也不多,这个文件的内容如下:

[BITS 32]                          ; 制作32位模式用的机器语言GLOBAL  _io_hlt, _io_cli, _io_sti, io_stihltGLOBAL  _io_in8,  _io_in16,  _io_in32GLOBAL  _io_out8, _io_out16, _io_out32GLOBAL  _io_load_eflags, _io_store_eflags
[SECTION .text]
_io_hlt:     ; void io_hlt(void);HLTRET
_io_cli:     ; void io_cli(void);CLIRET
_io_sti:     ; void io_sti(void);STIRET
_io_stihlt: ; void io_stihlt(void);STIHLTRET
_io_in8:     ; int io_in8(int port);MOV      EDX, [ESP+4]      ; portMOV      EAX,0IN       AL, DXRET
_io_in16:   ; int io_in16(int port);MOV      EDX, [ESP+4]      ; portMOV      EAX,0IN       AX, DXRET
_io_in32:   ; int io_in32(int port);MOV      EDX, [ESP+4]      ; portIN       EAX, DXRET
_io_out8:   ; void io_out8(int port, int data);MOV      EDX, [ESP+4]      ; portMOV      AL, [ESP+8]       ; dataOUT      DX, ALRET
_io_out16:  ; void io_out16(int port, int data);MOV      EDX, [ESP+4]      ; portMOV      EAX, [ESP+8]      ; dataOUT      DX, AXRET
_io_out32:  ; void io_out32(int port, int data);MOV      EDX, [ESP+4]      ; portMOV      EAX, [ESP+8]      ; dataOUT      DX, EAXRET
_io_load_eflags:     ; int io_load_eflags(void);PUSHFD       ; 指PUSH EFLAGSPOP      EAXRET
_io_store_eflags:   ; void io_store_eflags(int eflags);MOV      EAX, [ESP+4]PUSH EAXPOPFD ; 指POP EFLAGSRET

c入口文件修改

本次直接使用书中的C相关代码,但有几处不适配,需要我们单独进行修改

  1. 第一处是原书中的boxfill8函数,用于绘制矩形的:原书中是选循环y再循环x,但在博主运行时,总是会多出一个memset函数,导致运行失败,系统不断重启

需要将其修改下,替换为先循环x再循环y(不断地尝试后发现的,但没有搞懂为啥会这样)

  1. 第二处是调用boxfill8时的线条高度问题:原书中下发的两个矩形都是线条出度为1左右(我猜测),但在博主尝试中,小于3的高度不会显示

这里就需要修改下传入boxfill8的y0和y1的差值最小为3

经过修改后,文件的所有内容如下:

#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 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);void start(void)
{init_palette(); /* 设定调色板 */char *vram; /* 变量p是BYTE [...]用的地址 */vram = (char *) 0xa0000; /* 指定地址 */int xsize = 320;int ysize = 200;boxfill8(vram, xsize, COL8_008484,  0,         0,          xsize, ysize - 29);boxfill8(vram, xsize, COL8_C6C6C6,  0,         ysize - 28, xsize, ysize - 28);boxfill8(vram, xsize, COL8_FFFFFF,  0,         ysize - 27, xsize, ysize - 27);boxfill8(vram, xsize, COL8_C6C6C6,  0,         ysize - 26, xsize, ysize -  1);//     y距离有时候需要大于3boxfill8(vram, xsize, COL8_FFFFFF,  3,         ysize - 24, 59,         ysize - 21);boxfill8(vram, xsize, COL8_FFFFFF,  2,         ysize - 24,  2,         ysize -  4);boxfill8(vram, xsize, COL8_848484,  3,         ysize -  4, 59,         ysize -  1);boxfill8(vram, xsize, COL8_848484, 59,         ysize - 23, 59,         ysize -  5);boxfill8(vram, xsize, COL8_000000,  2,         ysize -  3, 59,         ysize -  0);boxfill8(vram, xsize, COL8_000000, 60,         ysize - 24, 60,         ysize -  3);boxfill8(vram, xsize, COL8_848484, xsize - 47, ysize - 24, xsize -  4, ysize - 21);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 -  0);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 (x = x0; x <= x1; x++) {for (y = y0; y <= y1; y++) {vram[y * xsize + x] = c;}}return;
}

脚本还是使用原来的,本篇中没有变化,一键运行后,出现文章开头令人激动的画面

初步感受C代码转汇编

在书中开始时介绍了不同手段实现同一个效果:给内存赋值

第一个方式是使用wirte_mem8时的编译nasm代码:使用写汇编函数的方式,根据传入的值,写到相应的内存中

void write_mem8(int addr, int data);
void start(void) {int i;for (i = 0xa0000; i < 0xaffff; i++) {write_mem8(i, i & 0x0f);}
}
ALIGN   8
?_001:  mov     eax, ebx                                ; 0018 _ 89. D8mov     dword [esp], ebx                        ; 001A _ 89. 1C 24add     ebx, 1                                  ; 001D _ 83. C3, 01and     eax, 0FH                                ; 0020 _ 83. E0, 0Fmov     dword [esp+4H], eax                     ; 0023 _ 89. 44 24, 04call    _write_mem8                             ; 0027 _ E8, 00000000(rel)cmp     ebx, 720895                             ; 002C _ 81. FB, 000AFFFFjnz     ?_001                                   ; 0032 _ 75, E4_write_mem8:     ; void write_mem8(int addr, int data);MOV      ECX, [ESP+4]      ; [ESP + 4]中存放的是地址,将其读入ECXMOV      AL, [ESP+8]       ; [ESP + 8]中存放的是数据,将其读入ALMOV      [ECX], ALRET

第二个是指针,使用char*时的编译nasm代码:突然有种回到以前学习C的感觉,想到初期使用指针时的痛苦

void start(void) {int i;char *p;for (i = 0xa0000; i < 0xaffff; i++) {p = (char *) i;*p = i & 0x0f;}/* 或者下面这样写,生成的汇编码也一样 */char *p;p = (char *) 0xa0000; /*将地址赋值进去*/for (i = 0; i <= 0xffff; i++) {p[i] = i & 0x0f;}
}
?_001:  mov     edx, eax                                ; 0018 _ 89. C2add     eax, 1                                  ; 001A _ 83. C0, 01and     edx, 0FH                                ; 001D _ 83. E2, 0Fmov     byte [eax-1H], dl                       ; 0020 _ 88. 50, FFcmp     eax, 720895                             ; 0023 _ 3D, 000AFFFFjnz     ?_001                                   ; 0028 _ 75, EE

可以看到两种不同的实现方式,对C的指针有了更深的理解,了解底层确实是有一定帮助的

总结

本文相对而言还是比较顺利的,虽然有一点坎坷,但在不断的调试中,顺利解决了

还进一步理解了C的指针

但关于书中的控制屏幕显示部分,目前还不是很通透,很需要再刷刷

相关内容

热门资讯

母亲的爱让我感动作文400字 关于母亲的爱让我感动作文400字三篇  在日复一日的学习、工作或生活中,大家最不陌生的就是作文了吧,...
感动中国作文 感动中国作文集合15篇  在现实生活或工作学习中,大家都不可避免地要接触到作文吧,作文是人们把记忆中...
秋天的果实作文 秋天的果实作文400字(精选5篇)  在我们平凡的日常里,许多人都写过作文吧,根据写作命题的特点,作...
快乐数学作文 快乐数学作文(通用24篇)  无论是在学校还是在社会中,大家都接触过作文吧,作文是一种言语活动,具有...
盛夏作文600字 【精选】盛夏作文600字(精选27篇)  在日常的学习、工作、生活中,大家一定都接触过作文吧,作文是...
令我感动的人作文 令我感动的人作文11篇  在现实生活或工作学习中,大家都接触过作文吧,通过作文可以把我们那些零零散散...
地球母亲作文300字 地球母亲作文300字(通用26篇)  在日常学习、工作抑或是生活中,大家都经常看到作文的身影吧,作文...
我亲爱的祖国作文300字 我亲爱的祖国作文300字(精选5篇)  无论是身处学校还是步入社会,大家都不可避免地要接触到作文吧,...
恩情-母亲 -作文 恩情-母亲 -作文初中 面对那最无私,最不求回报的恩情,我无从下手,恩情-母亲。来源:恩情,我能回...
前行作文600字 前行作文600字(通用10篇)  在平凡的学习、工作、生活中,大家都有写作文的经历,对作文很是熟悉吧...
甜甜的爱作文 甜甜的爱作文5篇  在现实生活或工作学习中,大家都经常接触到作文吧,根据写作命题的特点,作文可以分为...
肩膀作文350字 肩膀作文350字  在我满心伤痕的时候,我需要这样一个宽厚的肩膀给我力量;在我一心欢喜的时候,我需要...
新的校园新的环境作文600字 新的校园新的环境作文600字  导语:新的校园新的环境,一切都是新的开始。下面是小编为您带来的是新的...
灯笼作文 灯笼作文灯笼灯笼今天我和爸爸心血来潮做灯笼。我们找来了铁丝、彩纸、剪子、钳子等工具。本想做个园的大灯...
优美文章段落 优美文章段落  在学习、工作或生活中,大家一定没少看到经典的句子吧,从语气上分,句子可以分为陈述句、...
美人鱼作文 美人鱼作文(精选34篇)  在我们平凡的日常里,大家或多或少都会接触过作文吧,作文根据体裁的不同可以...
责任心350字作文 责任心350字作文  每个人,都有一定的责任。这个“责任”,是最基本的,就是对自己,对亲人,对朋友。...
我的学习生活作文 我的学习生活作文3篇  在日常学习、工作抑或是生活中,大家都经常接触到作文吧,作文是人们以书面形式表...
小时候的回忆作文 小时候的回忆作文(通用55篇)  在生活、工作和学习中,大家都跟作文打过交道吧,作文是人们把记忆中所...
国庆见闻作文 国庆见闻作文(通用20篇)  在我们平凡的日常里,大家最不陌生的就是作文了吧,作文是从内部言语向外部...