自制操作系统04
在今天的学习开始之前,先把windows下make环境搞好。之前以为要先安装MinGW才可以执行make命令,所以没有用windows下的make。而昨天看到要运行作者的代码,必须使用上作者的工具,而这些工具的使用并不需要第三方软件。
而make.exe也是其中一个工具,那么可能windows下的make命令只用这个文件就可以了。下面就主要在windows下做这些事情了。每个项目文件夹下有一个make.exe,再看makefile文件里有../z_tools/这样的相对路径。
那么我们每天首先需要做的事情就是把z_tools文件夹复制到每天的文件夹下,这样就可代码要求的路径一样了。
环境搭好后,再运行作者的代码真是太轻松了,控制台进入一个项目文件夹,输入make,回车,搞定。可以用虚拟机来运行生成的映像文件了。
说到这里,我有点失望了。说好自制的呢,怎么还得用工具?而且是作者写的专用工具,不是开源项目。作者的nask其实有源码,但又怎么样呢,以我现在的技术也不能编译和运行...
算了吧,还是搞点能搞明白的东西。作者即然改了编译器,那么原始的编译器是啥样的呢?
windows下可以从这里下载一个masm
http://www.masm32.com/download.htm
然后写一个masm的汇编程序:
可以注意到,这和我们之前写的汇编格式不一样。我们第一天的可以用nasm编译,这个可不行。可见我们的汇编程序并不是所有平台都可用,这也就是现在java能流行的原因,那个年代能做到一段代码能到多个平台运行的语言不多。
回到我们的自制操作系统问题上来,作者的HariMain(main)函数,离开了他的编译器就无法运行了。但我感觉还是要看下去,因为他也会从制作操作系统的角度来解释C语言,中断,IO,内存,并发等知识。但并不需要去详细分析每一句代码,
就算搞明白了,别的地方也用不上。所以后面的学习看到是通用的,就记下来,不是的就略过了。
好了,开始今天的内容。
先来一段汇编程序:
_write_mem8: ; void write_mem8(int addr, int data);
MOV ECX,[ESP+4] ; [ESP+4]にaddrが入っているのでそれをECXに読み込む
MOV AL,[ESP+8] ; [ESP+8]にdataが入っているのでそれをALに読み込む
MOV [ECX],AL
RET
这个和我们的高级语言的区别较大,明明是个_write_mem8函数,但两个参数 (addr,data)却根本没用,那还要他干啥?
哈哈,关键点在于这个ESP,回到第二天,有这么一句:
SP--stack pointer,栈指针寄存器
ESP就是extend stack pointer了,原来这就是函数的地址,函数地址+4就是addr的值(是个地址值),+8就是data的值。然后再把data写进addr。调用的c语言是这样:
for (i = 0xa0000; i <= 0xaffff; i++) {
write_mem8(i, 15); /* MOV BYTE [i],15 */
}
i的范围应该是显卡的显示的地址范围,15表示是白色,最后就是全白了。
如果颜色值改成i&0x0f,那么低4位不变,高4位会变。
write_mem8(i, i&0x0f);
效果如下图 :
把i地址的改成指针,居然就代替了内存修改,顺便把颜色值改下:
int *p;
for (i = 0xa0000; i <= 0xaffff; i++) {
//write_mem8(i, i&0x0f); /* MOV BYTE [i],15 */
p=i;
*p=i&0x02;
}
效果如下图 :
后面还有一个知识点:
如果p是指针(char *p),那么p[i]与*(p+i)等价。还有p[i]与i[p]等价。
c语言中,本文件后面的函数,其声明放前面。
后面设计到了中断,PUSHFD是push flags double-word(将EFLAGS的值保存进栈), POPFD是pop flags double-word(从栈里取值)。
_io_cli: ; void io_cli(void);
CLI ;中断标志置为0
RET
_io_sti: ; void io_sti(void);
STI ;中断标志置为1
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
简单来说,就是cpu中间要插个任务,就要做做这些事。
能出条纹当然就能画矩形了,不过地址不一样。
同理,再画个windows的基本桌面样子。
看到这个样子,还是有点想去点的冲动。
文/程忠 浏览次数:0次 2020-04-07 11:40:03
而make.exe也是其中一个工具,那么可能windows下的make命令只用这个文件就可以了。下面就主要在windows下做这些事情了。每个项目文件夹下有一个make.exe,再看makefile文件里有../z_tools/这样的相对路径。
那么我们每天首先需要做的事情就是把z_tools文件夹复制到每天的文件夹下,这样就可代码要求的路径一样了。
环境搭好后,再运行作者的代码真是太轻松了,控制台进入一个项目文件夹,输入make,回车,搞定。可以用虚拟机来运行生成的映像文件了。
说到这里,我有点失望了。说好自制的呢,怎么还得用工具?而且是作者写的专用工具,不是开源项目。作者的nask其实有源码,但又怎么样呢,以我现在的技术也不能编译和运行...
算了吧,还是搞点能搞明白的东西。作者即然改了编译器,那么原始的编译器是啥样的呢?
windows | linux | ||
汇编 | C | 汇编 | C |
ml.exe(编译器) link.exe(连接器) |
cl.exe vc编译,连接器 gcc mingw环境下编译,链接为exe文件 gcc cygwin环境下编译,链接为linux下文件 |
nasm | gcc |
windows下可以从这里下载一个masm
http://www.masm32.com/download.htm
然后写一个masm的汇编程序:
.386 .model flat,stdcall option casemap:none ;说明 includelib msvcrt.lib printf PROTO C :ptr sbyte,:VARARG ;数据区 .data szMsg byte "Hello World!",0ah,0 ;代码区 .code start: invoke printf,OFFSET szMsg ret end start
可以注意到,这和我们之前写的汇编格式不一样。我们第一天的可以用nasm编译,这个可不行。可见我们的汇编程序并不是所有平台都可用,这也就是现在java能流行的原因,那个年代能做到一段代码能到多个平台运行的语言不多。
回到我们的自制操作系统问题上来,作者的HariMain(main)函数,离开了他的编译器就无法运行了。但我感觉还是要看下去,因为他也会从制作操作系统的角度来解释C语言,中断,IO,内存,并发等知识。但并不需要去详细分析每一句代码,
就算搞明白了,别的地方也用不上。所以后面的学习看到是通用的,就记下来,不是的就略过了。
好了,开始今天的内容。
先来一段汇编程序:
_write_mem8: ; void write_mem8(int addr, int data);
MOV ECX,[ESP+4] ; [ESP+4]にaddrが入っているのでそれをECXに読み込む
MOV AL,[ESP+8] ; [ESP+8]にdataが入っているのでそれをALに読み込む
MOV [ECX],AL
RET
这个和我们的高级语言的区别较大,明明是个_write_mem8函数,但两个参数 (addr,data)却根本没用,那还要他干啥?
哈哈,关键点在于这个ESP,回到第二天,有这么一句:
SP--stack pointer,栈指针寄存器
ESP就是extend stack pointer了,原来这就是函数的地址,函数地址+4就是addr的值(是个地址值),+8就是data的值。然后再把data写进addr。调用的c语言是这样:
for (i = 0xa0000; i <= 0xaffff; i++) {
write_mem8(i, 15); /* MOV BYTE [i],15 */
}
i的范围应该是显卡的显示的地址范围,15表示是白色,最后就是全白了。
如果颜色值改成i&0x0f,那么低4位不变,高4位会变。
write_mem8(i, i&0x0f);
效果如下图 :
把i地址的改成指针,居然就代替了内存修改,顺便把颜色值改下:
int *p;
for (i = 0xa0000; i <= 0xaffff; i++) {
//write_mem8(i, i&0x0f); /* MOV BYTE [i],15 */
p=i;
*p=i&0x02;
}
效果如下图 :
后面还有一个知识点:
如果p是指针(char *p),那么p[i]与*(p+i)等价。还有p[i]与i[p]等价。
c语言中,本文件后面的函数,其声明放前面。
后面设计到了中断,PUSHFD是push flags double-word(将EFLAGS的值保存进栈), POPFD是pop flags double-word(从栈里取值)。
_io_cli: ; void io_cli(void);
CLI ;中断标志置为0
RET
_io_sti: ; void io_sti(void);
STI ;中断标志置为1
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
简单来说,就是cpu中间要插个任务,就要做做这些事。
能出条纹当然就能画矩形了,不过地址不一样。
同理,再画个windows的基本桌面样子。
看到这个样子,还是有点想去点的冲动。
相关阅读
评论:
↓ 广告开始-头部带绿为生活 ↓
↑ 广告结束-尾部支持多点击 ↑