任务:阅读实验一makefile 搞清楚ucore.img是如何构建的
$@ $< $^ 这三个变量分别是什么意思 https://blog.csdn.net/YEYUANGEN/article/details/36898505
=和:=的区别 https://stackoverflow.com/questions/448910/what-is-the-difference-between-the-gnu-makefile-variable-assignments-a
dd命令 http://www.runoob.com/linux/linux-comm-dd.html
call命令
通配符
$(call create_target,ucore.img)不懂,create_target是内置函数?
makefile教程:https://blog.csdn.net/special00/article/details/51084619 包含call 函数调用的说明
找到一个TsingHua大佬在github的实验:https://github.com/dongyp13/os_lab/blob/master/labcodes/lab1/lab1-%E8%91%A3%E8%83%A4%E8%93%AC.md
GCC的-fno-builtin选项 https://blog.csdn.net/baiyu9821179/article/details/73007124
-gstabs
此选项以stabs格式声称调试信息,但是不包括gdb调试信息.
-gstabs+
此选项以stabs格式声称调试信息,并且包含仅供gdb使用的额外调试信息.
-ggdb
此选项将尽可能的生成gdb的可以使用的调试信息.
GCC选项-g和-ggdb的区别 https://my.oschina.net/moooofly/blog/493859
Linux 中的 cc 命令 https://blog.csdn.net/candy060403/article/details/7519370
-nostdinc不要在标准系统目录中寻找头文件.只搜索`-I'选项指定的目录(以及当前目录,如果合适).
结合使用`-nostdinc'和`-I-'选项,你可以把包含文件搜索限制在显式指定的目录.
GCC 4.1 中三个与堆栈保护有关的编译选项
-fstack-protector:
启用堆栈保护,不过只为局部变量中含有 char 数组的函数插入保护代码。
-fstack-protector-all:
启用堆栈保护,为所有函数插入保护代码。
-fno-stack-protector:
禁用堆栈保护。
有关堆栈保护内容 https://www.ibm.com/developerworks/cn/linux/l-cn-gccstack/index.html
-Idir在头文件的搜索路径列表中添加dir 目录.
-I-任何在`-I-'前面用`-I'选项指定的搜索路径只适用于`#include "file"'这种情况;他们不能用来搜索`#include <file>'包含的头文件.
如果用`-I'选项指定的搜索路径位于`-I-'选项后面,就可以在这些路径中搜索所有的 `#include'指令. (一般说来-I选项就是这么用的.)
还有, `-I-'选项能够阻止当前目录(存放当前输入文件的地方)成为搜索`#include "file"'的第一选择.没有办法克服`-I-'选项的这个效应.你可以指定 `-I.'搜索那个目录,它在调用编译器时是当前目录.这和预处理器的默认行为不完全一样,但是结果通常 令人满意.
`-I-'不影响使用系统标准目录,因此, `-I-'和`-nostdinc'是不同的选项.
-Ldir在`-l'选项的搜索路径列表中添加dir目录.
关于fno-builtin和fno-builtin-function编译选项
https://blog.csdn.net/SstudentT/article/details/52910696
CLI https://en.wikipedia.org/wiki/Interrupt_flag
CLD https://en.wikipedia.org/wiki/Direction_flag#cite_note-1
A20地址线 https://blog.csdn.net/ruyanhai/article/details/7181842
gdb 跳过当前断点进入下一个断点时别忘了输入 c
fwrite和fread函数的用法小结 https://blog.csdn.net/sky_qing/article/details/12783045
100个gdb小技巧 https://wizardforcel.gitbooks.io/100-gdb-tips/print-registers.html
(伪,不确定)代码说明指令行为:x86 Instruction Set Reference https://c9x.me/x86/
Makefile 中命令的@,-@,+@符号 作用 https://blog.csdn.net/elfprincexu/article/details/51886620
实模式切换到保护模式,为什么要开启A20地址线(系统升级产生的兼容性问题)https://blog.csdn.net/PacosonSWJTU/article/details/48005813
某位大佬ucore实验1-3 https://blog.csdn.net/winkar/article/details/40017573
(硬件信息比较详细)ucore操作系统实验笔记 - Lab1-3 https://segmentfault.com/a/1190000009386091
某位大佬ucore实验1-8 https://blog.csdn.net/qq_19876131/article/details/51706973
ucore实验之操作系统启动流程 http://blog.xiaohansong.com/2015/10/02/ucore%E5%AE%9E%E9%AA%8C%E4%B9%8B%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B/
ucore实验结构和ex实验?http://os.cs.tsinghua.edu.cn/oscourse/ucore/2016
某位大佬ucore实验1-8 https://blog.csdn.net/ni9htmar3/article/category/6793322
ucore的makefile部分解释 https://blog.csdn.net/u013484370/article/details/50638353
ucore 1-8 https://blog.csdn.net/tangyuanzong/article/category/7110079
ucore2,3,4,6 https://blog.csdn.net/th_num/article/category/6148598
ucore1-8 https://blog.csdn.net/cs_assult/article/category/3273629
操作系统:ucore的部分Bug&挑战练习 https://blog.csdn.net/He11o_Liu/article/details/54028501
全局描述符表格式:https://blog.csdn.net/yuzhihui_no1/article/details/42386915
分段模式:https://www.csie.ntu.edu.tw/~wcchen/asm98/asm/proj/b85506061/chap2/segment.html
asm.h中 .word是什么意思:.word就是在这个地方放一个值。相当于在这里定义一个数据变量。用.word定义了一个16bit的数据。http://sdnydubing.blog.163.com/blog/static/13747057020112904958830/
.byte应该就是8bit的数据变量吧?http://qvb3d.iteye.com/blog/1172510
段描述符:https://blog.csdn.net/longintchar/article/details/50489889
段描述符:http://guojing.me/linux-kernel-architecture/posts/segment-descriptor/
初始化各种段描述符:https://www.cnblogs.com/pacoson/p/4893177.html
关于asm.h 中的汇编宏
#define SEG_ASM(type,base,lim)
.word (((lim) >> 12) & 0xffff), ((base) & 0xffff);
.byte (((base) >> 16) & 0xff), (0x90 | (type)),
(0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)
这个是声明了两个16bit的数据变量和4个8bit的数据变量
段描述符是上下两条 一共64bit
关于上面这个汇编宏是考虑了大小端的,此处考虑x86是小端模式,即高位高地址,低位低地址,然后存的时候我们默认先从内存的低地址开始存
ljmp的含义:
0xffff0: ljmp $0xf000,$0xe05b
也就是说,BIOS开始的地址应该是 $cs << 4 | 0xe05b = 0xfe05b
# ljmp <imm1>, <imm2>
# %cs ← imm1
# %ip ← imm2
关于ljmp:
(7) |
远程的转移指令和子程序调用指令的操作码名称,在AT&T格式中为“ljmp”和“lcall气而 在Intel格式中,则为"JMP FAR"和"CALL FAR"。当转移和调用的目标为直接操作数时, 两种不同的表示如下: CALL FAR SECTION:OFFSET (Intel格式) JMP FAR SECTIOM:OFFSET (Intel格式) lcall $section, $offset (AT&T格式) ljmp $section,$offset (AT&T格式) 与之相应的远程返回指令,则为: RET FAR STACK_ADJUST(Intel格式) lret $stack_adjust (AT&T格式) |
由于我们要将实模式切换为保护模式,所以要关掉A20地址线,A20地址线的关闭要通过与Intel 8042控制器进行通信来实现
主要用到8042的两个端口
PS/2 compatibles.
IO Port | Access Type | Purpose |
---|---|---|
0x60 | Read/Write | Data Port |
0x64 | Read | Status Register |
0x64 | Write | Command Register |
然后0x64是命令端口,0x60是数据端口
进行操作时要首先考虑该设备的状态信息,即缓冲区是否为空
Bit | Meaning |
---|---|
0 | Output buffer status (0 = empty, 1 = full)
(must be set before attempting to read data from IO port 0x60) |
1 | Input buffer status (0 = empty, 1 = full)
(must be clear before attempting to write data to IO port 0x60 or IO port 0x64) |
2 | System Flag
Meant to be cleared on reset and set by firmware (via. PS/2 Controller Configuration Byte) if the system passes self tests (POST) |
3 | Command/data (0 = data written to input buffer is data for PS/2 device, 1 = data written to input buffer is data for PS/2 controller command) |
4 | Unknown (chipset specific)
May be "keyboard lock" (more likely unused on modern systems) |
5 | Unknown (chipset specific)
May be "receive time-out" or "second PS/2 port output buffer full" |
6 | Time-out error (0 = no error, 1 = time-out error) |
7 | Parity error (0 = no error, 1 = parity error) |
流程是,检查状态,缓冲区为空就写入命令端口,再次检查状态,缓冲区为空就写入数据端口将A20地址线标志位置位关闭
BIOS是系统自己的固件,不用管,当BIOS启动后的某一个阶段会将ucore.img?load 到0x7c00,然后将控制权交给0x7c00
而0x7c00后面就是我们的bootasm.S以及后面调用的bootmain.c合并之后的汇编代码
bootasm.S将A20关闭,定义了代码段和数据段的GDT表项,然后将栈空间定义为0x0000到0x7c00并且在这里呼叫了bootmain.c中的bootmain函数
bootmain在干什么尚不清楚,稍后研究。更新:bootmain是用来将文件kernel(elf格式)加载到内存中去,也就是解析elf格式的内核文件,elf:executable linkable file
bootmain连续加载了磁盘扇区(位于bootloader后面的连续的四个扇区),然后进行elf的解析
系统启动流程
1.系统加电 BIOS初始化硬件
2.BIOS读取主引导扇区代码
3.主引导扇区的代码读取活动分区的引导扇区代码
4.引导扇区的代码读取文件系统中的加载程序
加载程序bootloader
1.从文件系统中读取启动配置信息(加载程序)
2.启动菜单:可选的操作系统内核列表和加载参数
3.依据配置加载指定内核并跳转到内核执行
IRQ Numbers:https://www.webopedia.com/quick_ref/IRQnumbers.asp
中断向量符表:http://guojing.me/linux-kernel-architecture/posts/interrupt-descriptor-table/
又一位大佬(UESTC)的ucore实验1:http://xr1s.me/2018/05/15/ucore-lab1-report/
貌似gdb target链接qemu之后只能si调试了???https://github.com/chyyuu/ucore_os_lab/issues/39
calltree 查看函数调用 http://blog.51cto.com/chenqin/977113
各种段寄存器:https://wiki.osdev.org/CPU_Registers_x86#EFLAGS_Register
pusha指令:https://blog.csdn.net/ross1206/article/details/72831209 https://c9x.me/x86/html/file_module_x86_id_270.html
trapframe数据结构:http://www.cnblogs.com/fanzi2009/archive/2011/04/07/2008144.html
IBM内联汇编教程:https://www.ibm.com/developerworks/cn/linux/sdk/assemble/inline/index.html
中断指令以及中断和异常控制在x86手册的位置:https://c9x.me/x86/html/file_module_x86_id_142.html