终于从科研中抽出身来搞一搞自己的项目,MiniOS目前到了第8章了,越深入下去不懂的地方也就越多。
你能递归的去死磕一个问题多深,并且能安全的返回到原来你最初想要解决的问题,没有"爆栈",那么这个深度就代表你的学习能力。深度越深,学习能力越强。人不可能一直拥有一个足够舒适的环境去系统地把所有东西都搞定,不可能把所有的基础知识都搞定了再上项目,去解决实际问题。在实际问题中发现问题,解决问题,才是真真的学习能力!!!不是TM卷子上多少分!
目前最难懂部分还是汇编。之前看王爽的《汇编语言》,这本书虽然易懂,但是对应到目前操作系统的底层汇编代码,还是不够。再次踏上汇编的学习之路,目前在看《X86汇编语言:从实模式到保护模式》和《深度理解计算机系统》第三章。
本篇所有的描述都是AT&T格式的汇编
汇编的补充知识
基本指令
源操作数指定的值是一个立即数,存储在寄存器或者内存中。目的操作数指定一个位置,要么是一个寄存器,要么是一个内存地址。x86-64加了一条限制,传送指令的两个操作数不能都指向内存位置。 将一个值从一个内存位置复制到另一个内存位置需要两条指令——第一条指令将源值加载到寄存器中,第二条将该寄存器值写入目的位置。
movl
指令以寄存器为目的时,它会把该寄存器的高位4字节设置为0。 movabsq
指令只能以寄存器作为目的。
栈向下增长。栈顶元素的地址是所有栈中元素地址中最低的。
leaq
的指令形式是从内存读数据到寄存器,但实际上它根本没有引用内存。它并不是从指定的位置读入数据,而是将有效地址写入到目的操作数。
SAL
和SHL
的效果是一样的,都是将右边填上0。SAR
执行算数移位(填上符号位),SHR
执行逻辑移位(填上0)。
CMP
指令根据两个操作数之差来设置条件码,除了只设置条件码而不更新目的寄存器的值之外,CMP
指令与SUB
指令的行为是一样的。TEST
指令的行为与AND
指令一样,除了它只有设置条件码而不改变目的寄存器的值。
使用数据的条件转移来代替控制的条件转移,可以提高处理器的执行效率。
对求绝对值函数
1 | long absdiff(long x, long y){ |
改成
1 | long cmovdiff(long x, long y){ |
处理器通过流水线来获得高性能。所谓流水线,是指重叠连续指令的步骤,例如,在取一条指令的同时,执行它前面一条指令的算数运算。这要求处理器要能事先确定执行的指令序列。当遇到条件跳转时,只有当分支条件求值完成之后才能决定分支往哪边走。一旦错误预测了一个跳转,要求处理器丢掉它为该跳转指令后所有指令已做的工作,然后再开始用从正确位置处起始的指令填充流水线,导致程序性能严重下降。 而使用条件传送的代码,控制流不依赖于数据,这使得处理器更容易保持流水线是满的。这一块的内容详见CSAPP的第四章。
在学习栈这一节的时候,我被“调用者保存寄存器”和“非调用者保存寄存器”搞迷糊了,在看汇编代码和B栈九曲阑干讲的CSAPP时更蒙了,还好这里有一篇博客【CSAPP】背景知识-调用者保存寄存器与被调用者保存寄存器,在此贴出来帮助以后复习,也希望能帮助到更多的人。
---------------------------to be continued-----------------------------