第八周学习及期中考试总结
一: 1:Linux命令
登录Linux后,我们就可以在#或$符后面去输入命令,有的时候命令后面还会跟着选项
(options)或参数
(arguments).
即Linux中命令格式为:command[options][arguments]。但有些命令也不需要跟着选项或参数。
2 :man命令
1是普通的Linux命令(用户命令帮助)
2是系统调用,操作系统的提供的服务接口(系统调用帮助)
3是库函数, C语言中的函数(库函数调用帮助)
4:man-k命令
结合grep和管道,实现多关键字查找:man-k key1等
3:cheat 命令
cheat命令是在GNU通用公共许可证下,为Linux命令行用户发行的交互式备忘单应用程序。简称:小抄的命令。
4:其他核心命令
和查找相关的核心命令还有find
,locate
,grep
,whereis
,which
。
其中:grep-nr xxx/usr/include:想查找某个宏,我们已知宏保存在include
文件夹中。
这条语句可以用来查找关键字,全文搜索,并且可以直接查找文件内的内容。 n:为显示行号 r:为递归查找
二:第二章
其中主要包含了一些代码,比如:十进制与十六进制的转换。十六进制的输出,
位的扩展和截断等。大多数机器对整数使用补码编码,而对浮点数使用IEEE浮点编码。在相同长度的无符号和有符号整数之间进行强制类型转换时,大多数C语言实现遵循的原则是底层的位模式不变。在补码机器上,对于一个W位的值,这种行为是由函数T2Uw和U2Tw来描述的。
c
语言基本数据类型对应的
IA32
表示
char 字节 1字节 short 字 2字节 int 双字 4字节 long int 双字 4字节 long long int (不支持) 4字节 char * 双字 4字节 float 单精度 4字节 double 双精度 8字节 longdouble 扩展精度 10/12字节。
小端法大端法
—最低有效字节在最前面的方式,称为小端法(little endian)。大多数Intel 兼容机都采用这种规则。
后一种规则—最高有效字节在最前面的方式,称为大端法(big endian)。大多数IBM 和Sun Microsystems 的机器都采用这种规则。注意我们说的是"大多数"。这些规则并没有严格按照企业界限来划分。
小端是"高对高、低对低",大端与之相反
布尔代数
二进制值是计算机编码、存储、操作信息的核心(0、1)
逻辑运算——
0
或
1
位运算————位向量
三:vim/gcc/gdb/make的使用
1:vim
编辑多个文件有两种形式,一种是在进入vim前使用的参数就是多个文件。另一种就是进入vim后再编辑其他的文件。
同时创建两个新文件并编辑 $ vim 1.txt 2.txt。
文件的编辑界面
1.txt
- 命令行模式下输入
:n
编辑2.txt文件,可以加!
即:n!
强制切换,之前一个文件的输入没有保存,仅仅切换到另一个文件 - 命令行模式下输入
:N
编辑1.txt文件,可以加!
即:N!
强制切换,之前文件内的输入没有保存,仅仅是切换到另一个文件 - 命令行模式下输入
:e
打开新文件3.txt
3.txt - 命令行模式下输入
:e#
回到前一个文件 - 命令行模式下输入
:ls
可以列出以前编辑过的文档 - 命令行模式下输入
:b
(或者编号)可以直接进入文件2.txt编辑
2.txt - 命令行模式下输入
:bd
(或者编号)可以删除以前编辑过的列表中的文件项目
2.txt - 命令行模式下输入
:e!
,新打开文件4.txt,放弃正在编辑的文件
4.txt - 命令行模式下输入
:f
显示正在编辑的文件名 - 命令行模式下输入
:f new.txt
,改变正在编辑的文件名字为new.txt
采用恢复方式,vim -r
进入文档后,输入:ewcover 1.txt
来恢复 $
vim -r 1.txt。
普通→插入: i/a
普通→命令行: “:”
插入/命令行→普通: Esc 或 Ctrl
+ [
常用操作:vim 文件名:进入vim,还可新建文件
命令行模式下 :wq 表示保存并退出。
2:GCC
gcc 编译程序的流程
源文件---预处理---编译---汇编----链接----可执行文件
gcc流程:
1、gcc会调用预处理程序cpp,由它负责展开在源程序中定义的宏(上例:#include <stdio.h>),向其中插入#include语句所包含的内容(展开stdio.h包含的代码)
在Xfce终端中输入:$ gcc -E hello.c -o hello.i
hello.i这是一个经过预处理器处理之后的C源文件
gcc的-E参数可以让gcc在预处理结束后停止编译过程。
2、将hello.i编译为目标代码,gcc默认将.i文件看成是预处理后的C语言源代码,因此它会直接跳过预处理,开始编译过程。
$ gcc -c hello.i -o hello.o
同样,用vim打开.o文件看,应该是一片乱码(它已经是二进制文件了)
Tips:
- 请记住,gcc预处理源文件的时候(第一步),不会进行语法错误的检查
- 语法检查会在第二步进行,比如花括号不匹配、行末尾没有分号、关键字错误......
3、gcc连接器将目标文件链接为一个可执行文件,一个大致的编译流程结束 gcc hello.o -o hello
。
3:GDB
GDB最基本的命令有:
- gdb programm(启动GDB)b 设断点(要会设4种断点:行断点、函数断点、条件断点、临时断点)
四种断点:
1.行断点 b [行数或函数名] <条件表达式>
2.函数断点 b [函数名] <条件表达式>
3.条件断点 b [行数或函数名] <if表达式>
4.临时断点 tbreak [行数或函数名] <条件表达式>
- run 开始运行程序
- bt 打印函数调用堆栈
- p 查看变量值
- c 从当前断点继续运行到下一个断点
- n 单步运行
- s 单步运行
- quit 退出GDB
gdb主要调试的是C/C++的程序。要调试C/C++的程序,首先在编译时,必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的 -g 参数即可。
如:$ gcc -g hello.c -o hello
$ g++ -g hello.cpp -o hello
4:make
make执行的动作,通常是把指定的相关文件编译成目标文件的编译命令,每个命令占一行,并以tab开头(初学者务必注意:是tab,而不是空格) 执行以上Makefile后就会自动化编译:
$ make
gcc -c prog.c -o prog.o
gcc -c code.c -o code.o
gcc prog.o code.o -o
test
最后就会多产生: porg.o code.o test这三个文件,执行./test
查看结果
还记得Makefile中的clean
吗? make clean
就会去执行rm -f *.o test
这条命令,完成 clean 操作。
使用带宏的 Makefile
Makefile还可以定义和使用宏(也称做变量),从而使其更加自动化,更加灵活,在Makefile中定义宏的格式为:
macroname = macrotext
使用宏的格式为:
$(macroname)
三:第三章
1:算术和逻辑操作
按目的操作数分类:
第一类:加载有效地址。实际是将有效地址写入目的操作数,目的操作数必须是寄存器。
第二类:一元操作。操作数既是源又是目的。可以是寄存器也可以是存储器。
第三类:二元操作。第二个操作数既是源又是目的。但两个操作数不能同时是存储器。
第四类:移位操作。位移量是一个立即数或放在单字节寄存器%cl中。移位操作的目的操作数可以是一个寄存器或是一个存储器位置。
SAL 算术左移SHL 逻辑左移SAR 算术右移(补符号位)SHR 逻辑右移(补0)
源操作数:移位量——立即数或CL
目的操作数:要移位的数值——寄存器或存储器。
2:机器级编程的两种抽象
a:指令集结构ISA是机器级程序的格式和行为,定义了处理器状态、指令的格式,以及每条指令对状态的影响。
b:机器级程序使用的存储器地址是虚拟地址,看上去是一个非常大的字节数组,实际上是将多个硬件存储器和操作系统软件组合起来。
3:X86(Intel处理器系列) 寻址方式经历三代:
1 DOS时代的平坦模式,不区分用户空间和内核空间,很不安全
2 8086的分段模式
3 IA32的带保护模式的平坦模式。
4:操作数的三种类型
立即数:常数值
寄存器:某个寄存器的内容
存储器:根据计算出来的地址访问某个存储器位置
四:第四章
1:栈 :栈帧结构
栈用来传递参数、存储返回信息、保存寄存器,以及本地存储。
定义:为单个过程分配的那部分栈称为栈帧(本质上栈帧还是栈)。
2.最顶端的栈帧以两个指针界定:
寄存器%ebp-帧指针;寄存器%esp-栈指针。
栈指针可移动,所以信息访问多相对于帧指针。
3:Y86程序中的每条指令都会读取或修改处理器状态的某些部分,称为程序员可见状态。
8个程序寄存器:%eax,%ecx,%edx,%ebx,%esi,%edi,%esp,%ebp
寄存器%esp被入栈,出栈,调用和返回指令作为栈指针.
4:将处理组织成阶段
- 取指:从存储器读取指令字节,地址为程序计数器(PC)的值。指令指示符字节两个四位部分,称为icode(指令代码)和ifun(指令功能)。vaIP(下一条指令的地址)=PC+已取出指令的长度。?
- 译码:从寄存器文件读入最多两个操作数,得到valA和/或valB。?
- 执行:算数逻辑单元(ALU)根据ifun的值执行指令指明的操作,计算存储器引用的有效地址,或者增加或减少栈指针。得到的值称为valE。也可根据条件码执行跳转。?
- 访存:将数据写入存储器,或者从存储器读出数据。读出的值为valM。?
- 写回:最多可以写两个结果到寄存器文件。?
- 更新PC:将PC设置成下一条指令的地址。?
五:正则表达式
规则:
- \ 特殊符号,表示后面的字符本身?
- [ ] 匹配其中任意字符,但每次匹配只匹配一个?
- [^ ] 匹配除其中的任意字符,每次匹配只匹配一个?
- {n} 次数修饰,重复n次,具体如下:??= {0,1}
- += {1, }
- *= {0, }
- {m,n}:至少为m,至多为n??匹配方法:?
- ^ 从字符串开始的地方匹配?
- $ 从字符串结束的地方匹配?
六:第六章
1:存储器层次结构中的缓存
高速缓存是一个小而快速的存储设备,作为存储在更大、也更慢的设备中的数据对象的缓冲区域。使用高速缓存的过程称为缓存。
存储器层次结构的中心思想是:每一层都缓存来自较低一层的数据对象。
第k+1层的存储器被划分为连续的数据对象片,称为块。
类似第k层也被划分为较少的块的集合,块的大小与k+1层是一样的,第k层的缓存包含第k+1层块的一个子集的拷贝。
数据总是以块为传送单元在两层之间来回拷贝。不同层次对之间可以有不同的块大小。
a :缓存命中及缓存不命中
缓存命中:当程序需要第(k+1)层的数据对象d的时候,首先会在第k层找d;如果d刚好缓存在第k层,那么就叫做缓存命中;反之,不命中
如果缓存不命中,那么第k层缓存就从第(k+1)层取出包含该数据的块,有可能会覆盖现有的块。覆=决定替换哪个块是由缓存的替换策略来控制的。
b:缓存管理
指某个东西要将缓存划分成块,在不同层之间传递块,判定是命中还是不命中,并处理他们。
管理缓存的逻辑可以是硬件、软件或两者的结合。
2
:访问主存
数据流通过总线的共享电子电路在处理器和DRAM中来来回回。
每次传送都是通过一系列步骤完成的,称为总线事务。
读事务:从主存传送数据到CPU。写事务:从CPU传送数据到主存。
总线:一行并行的导线,能携带地址、数据和控制信号。
总线分类:
a.系统总线——连接CPU和I/O桥
控制总线:控制CPU与内存以及I/O设备之间的数据。
传送方式:读/写
数据总线:传递数据,决定CPU所能存取的位数。
总线越宽,CPU处理的能力越强。
地址总线:指出内存单元的地址,决定了最大可编程的内存空间。
N位地址,提供2的N次方个不同地址0~2的N次方-1。
b.存储器总线——连接I/O桥和主存
c.I/O 桥
I/O桥将系统总线的电子信号翻译成存储器总线的电子信号,也将系统总线和存储器总线连接到I/O总线。
3:局部性
时间局部性:被引用过一次的存储器位置很可能在不远的将来再被多次引用。
空间局部性:如果一个存储器位置被引用了一次,那么很可能在不远的将来引用附近的一个存储器位置。
对程序数据引用的局部性
取指令的局部性
量化评价一个程序中局部性的简单原则:
重复引用同一个变量的程序有良好的时间局部性。
对于具有步长为k的引用模式的程序,步长越小,空间局部性越好。
对于取指令来说,循环有很好的时间和空间局部性。循环体越小,循环迭代次数越多,局部性越好。
七:学习总结
在大学里,还是第一次遇到 这么负责任的老师,愿意全心全意的把自己的心血花在学生的心思上。刚开始学习的时候,只觉得任务很多,觉得自己一直在赶,赶着学习。急着完成任务,只怕自己任务完成不了。现在,已经适应了老师的教课方法。刚开始接触的时候,觉得很困难,只能按部就班。现在已经逐渐的理解问题并且思考问题。觉得自己学的只是皮毛,还要更用功才行。并且觉得只有循序渐进,不慌才能更好的解决问题。自己的自学能力已经在不断的提高了,只是知识点的捕捉能力还有待提升。其次,对计算机数据的输出也有了深入的了解。还有处理器和存储器的结构等。觉得计算机并不是那么枯燥,还是挺有意思的,希望自己能慢慢的深入的继续学习。
八:不足
感觉忘记知识比较快,命令什么的记得不全而且不够准确,是由于练习太少的原因。没有及时的巩固和复习。看书的时候效率太低。有的时候,也太注意blong的格式,感觉自己写的太慢。希望在以后的学习中不断地改进自己的问题,有更好更大的进步。