厦门安能建设公司网站,合肥建设企业网站,河北省建设厅正规网站,建设部标准定额研究所网站写在前面的话#xff1a;此系列文章为笔者学习CSAPP时的个人笔记#xff0c;分享出来与大家学习交流#xff0c;目录大体与《深入理解计算机系统》书本一致。因是初次预习时写的笔记#xff0c;在复习回看时发现部分内容存在一些小问题#xff0c;因时间紧张来不及再次整理… 写在前面的话此系列文章为笔者学习CSAPP时的个人笔记分享出来与大家学习交流目录大体与《深入理解计算机系统》书本一致。因是初次预习时写的笔记在复习回看时发现部分内容存在一些小问题因时间紧张来不及再次整理总结希望读者理解。 《深入理解计算机系统(CSAPP)》第3章 程序的机器级表示 - 学习笔记_友人帐_的博客-CSDN博客 
《深入理解计算机系统(CSAPP)》第5章 优化程序性能 - 学习笔记_友人帐_的博客-CSDN博客 
《深入理解计算机系统(CSAPP)》第6章 存储器层次结构 - 学习笔记_友人帐_的博客-CSDN博客 
《深入理解计算机系统(CSAPP)》第7章 链接- 学习笔记_友人帐_的博客-CSDN博客 
《深入理解计算机系统(CSAPP)》第8章 异常控制流 - 学习笔记_友人帐_的博客-CSDN博客 
《深入理解计算机系统(CSAPP)》第9章虚拟内存 - 学习笔记_友人帐_的博客-CSDN博客 第三章 程序的机器级表示 
1. 代码编译过程 
gcc -Og -o hello source1.c source2.c ...gcc -Og -S -fno-if-conversion source.c  // 优化等级低便于理解注①-Og为代码优化等级②-o表示生成可执行文件-s可以生成汇编代码③生成实际可执行的代码需要对一组目标代码文件运行链接器而这一组目标代码文件中必须含有一个main函数④有时会在末尾(return后)有90 nop指令目的是为了使函数代码变为16字节使得存储器能更好地放置下一个代码块提高性能。 
源代码转化为可执行代码 
①C预处理器扩展源代码插入所有用#include命令指定的文件并扩展所有#define声明指定的宏 
②编译器生成源文件的汇编代码后缀.s 
③汇编器将汇编代码转化为二进制目标代码文件后缀.o 
④链接器将目标代码文件与实现库函数的代码合并填入全局值的地址生成可执行代码文件。 
GDB调试指令  
2. 反汇编 
反汇编将可执行二进制文件翻译为汇编语言 
objdump -d target.o
objdump -S target.o  target.txt    (在反汇编中加入C代码且重定向输出到target.txt)
cat target.txt   查看3. 汇编相关ATT格式 
3.1 伪指令 
所有以.开头的指令都是指导汇编器和链接器工作的伪指令 
3.2 汇编代码后缀 3.3 寄存器 
1通用寄存器  
规则生成1字节和2字节数字的指令会保持剩下的字节不变生成4字节数字的指令会把高位4个字节置为0。 
2段寄存器 3指令指针寄存器EIP/PC 4EFLAGS寄存器 5系统寄存器 6浮点单元FPU 3.4 操作数指示符 
操作数类型 
①立即数用$符号表示代表常数值 
②寄存器直接访问寄存器的值 
③内存寻址 I m m ( R b , R i , S )  I m m  R b  R i ∗ S Imm(R_b,R_i,S)ImmR_bR_i*S Imm(Rb,Ri,S)ImmRbRi∗S其中 I m m Imm Imm表示立即数偏移 R b R_b Rb表示基址寄存器 R i R_i Ri表示变址寄存器 S S S为比例因子仅能取值1,2,4,8。计算得到的为一个地址相当于解引用操作。 
3.5 mov指令 注意 
①两个操作数不能同时指向内存位置。 
②寄存器部分的大小必须与指令最后一个字符(‘b’‘w’‘l’‘q’)指定的大小匹配。大多数情况MOV指令只会更新目的操作数指定的寄存器字节或内存位置但当movl指令以寄存器作为目的时会把该寄存器的高4位设置为0任何为寄存器生成32位值的指令都会把该寄存器的高位部分置为0。 
③不要给%rsp赋值系统保留。 扩展 - 零扩展(movz)、符号扩展(movs)大小指示符(源目的)  
条件传送 cmovcc src, dst cc表示条件使用EFLAGS中的条件码实现条件判断 对于无符号数使用a,b,e,b,c分别表示大于、小于、等于、否定、进位 对于有符号数使用g,l,e,n,o分别表示大于、小于、等于、否定、溢出 3.6 栈操作 
栈向下增长栈顶为低地址。 
指令 示意  
3.7 算术和逻辑操作 注意 
leaq并不是取源S的地址放入寄存器D而是将有效地址放入例如若%rdx值为x则指令leap 7(%rdx, %rdx, x) %rax将寄存器%rax的值设置为5x7 
特殊的算数操作八字 3.8 调试常用指令 编译./mak64 try64调试gdb ./try64设置断点b _start打开源代码窗口layout src layout split - 上方源代码下方汇编  打开寄存器观察窗口tui r g r表示registerg表示general通用寄存器  运行r  在断点处停止后单步运行n  4. IA32的内存管理 
4.1 实地址模式 实地址模式存储内容为真实物理地址。 
内存分段16位地址线不能直接表示20位地址采用内存分段方式使用两个16位地址来表示。表示为段地址段内偏移量约定段地址低4为为0便可以用16位地址表示段地址如此将内存空间划分为64KB的段。而实际地址可以采用实际地址  段地址0  段内偏移量计算得到段地址后补 0 16 0_{16} 016。 4.2 保护模式 
将段描述符(8字节段的相关信息)在段描述符表中的索引值存放在段寄存器(2字节)中。而在段描述符表中的每一行(每一个段描述符)都保存了段的相关参数、访问权限等信息。 GDT(全局描述符表)和LDT(局部描述符表)都用来存放各种描述符例如段描述符但这掩盖不了它们也是内存段的事实。简单地讲他们也是段。但是因为它们用于系统管理故称为系统的段或者系统段。GDT是唯一的整个系统中只有一个所以只需要用GDTR寄存器(CPU中)存放其线性基地址和段界限即可。其中存储了操作系统使用的代码段、数据段、堆栈段的描述符以及各个程序的LDT段但LDT不同每个程序有一个独立的LDT存放了对应程序的代码段、数据段、堆栈段的描述符等信息。当要使用这些LDT时可以用它们的选择子来访问GDT将LDT描述符加载到LDTR寄存器。 
全局描述符表寄存器GDTR(48位)指向GDT在内存中的地址。局部描述符表寄存器LDTR(16位)指向LDT段在GDT中的索引。 
在段选择器(保护模式下的段寄存器)中 1平坦分段模式 
而在段描述符表中(16进制)所有段被映射到32位物理地址空间程序至少分为代码段和数据段两个段。 
全局描述符表GDT 
基址(32位)指向段的起始地址图示中指向0000 0000很低的地址空间为操作系统所用 
界限指该段的长度其中0040是相对值要在后方加上000(乘以4k)即0040 000也说明了段的大小都是4k的倍数。  
2多段模式 
局部描述符表LDT 保护模式下的段寻址总结 3内存分页 5. 控制(条件、循环、分支) 
5.1 条件码 
CF进位标志。最高有效位有进位(无符号溢出)置为1否则置0。 
ZF零标志。最近的操作得出的结果为0。 
SF符号标志。最近的操作得到的结果为负数。 
OF溢出标志。最近的操作导致一个补码溢出(正溢出或负溢出) 
除了leaq指令其余算术和逻辑操作都伴随着进位标志的设置。 
还有一些指令只用于设置条件吗而不改变任何其他寄存器。 SET指令可以通过条件码的组合来进行各种条件操作(指令的后缀表示不同的条件而不是操作数大小)。目的操作数是低位单字节寄存器元素之一或是一个字节的内存位置指令会将这个字节设置为0或1。 cmp指令 
cmpq src1, src2计算src2-src1的值和0比较仅用结果设置条件码而不改变目的操作数。 
test指令 
testq src2, src1根据src2  src1 的数值来设置条件码结果并不保存通常将其中一个操作数看作是一个掩码。 
5.2 跳转指令jump 
jump指令会导致执行切换到程序中一个全新的位置。在汇编中这些跳转的目的地通常用一个标号(label)指明。 直接跳转jmp .L1 直接跳转到L1标号位置 间接跳转jmp *%rax 以%rax中的值作为读地址从内存中读出跳转目标 注跳转条件为1表示无条件跳转。 
跳转指令的编码 
PC相对跳转 
绝对地址跳转 
5.3 用条件控制来实现条件分支 
将if转化为goto类型直接对应于汇编。 if-else的通用转换模板 
// if-else版本
if (test-expr)then-statement
elseelse-statement// goto版本t  test-expr;if (!t)goto false;then-statementgoto done;
false:else-statement
done:使用数据的条件转移来实现条件分支的好处 将未知的跳转转换为已知的计算消除不确定性 
可以使得CPU的流水线中充满了待执行的指令避免条件预测逻辑(猜测每条跳转指令是否会执行)预测错误而导致浪费CPU的时钟周期以提高流水线性能。 
条件传送指令 5.4 循环 
用条件测试和跳转组合起来实现循环do-while、while、for 
// do-while通用形式
dobody-statementwhile (test-expr);// goto形式
loop:body-statementt  test-expr;if (t)goto loop;/* ----------------- */
// while 通用形式
while (test-expr)body-statement// while goto形式1 - 跳转到中间goto test;
loop:body-statement
test:t  test-expr;if (t)goto loop;// while goto形式2 - guarded-do
// 先翻译为do-while再翻译为goto
t  test-expr;
if (!t)goto done;
loop:body-statementt  test-expr;if (t)goto loop;
done:/* ----------------- */
// for 通用形式
for (init-expr; test-expr; update-expr)body-statement// for转化为while
init-expr;
while (test-expr) {body-statementupdate-expr;
}5.5 switch语句 
连续性较好的switch语句用跳转表不好的用决策树一堆if else 
switch使用跳转表一个数组表项 i i i是一个代码段的地址这个代码段实现当switch索引值等于 i i i时程序所执行的指令。当switch情况比较多时(4)并且值的范围跨度比较小时就会使用跳转表。跳转表的优点是执行语句的时间与情况数量无关。 
跳转表对重复情况的处理就是简单地使用相同的代码标号而对于缺失的情况的处理就是使用默认情况的标号(loc_def) 
6. 函数过程 
6.1 过程机制 
**传递控制**调用时转到调用过程代码的起始位置结束时回到返回点。 
**传递数据**过程参数与返回值的传递。 
**内存管理**过程运行期间申请内存返回时解除分配。 
该机制全部由机器指令实现。 
6.2 栈 
栈的结构  
注意①%rsp始终指向栈顶元素的位置。②向低地址生长。 
栈的操作 入栈指令pushq src 从src取操作数 → 将%rsp减8 → 将操作数写到%rsp指向的位置 出栈指令popq dst 从%rsp中保存的地址处读取数值 → 将%rsp加8 → 将数值保存到dst(dst必须为寄存器或内存操作数) 6.3 过程控制流 
过程调用 
call func_label 
执行操作 
①将返回地址入栈(返回地址即为紧随call指令的下一条指令的地址) 
②跳转到func_label(函数名字就是函数代码段的起始地址) 
过程返回 
ret 
执行操作 
从栈中弹出返回地址放入%rip里(pc) 
参数传递 返回值%rax 
局部变量仅在需要时申请栈空间 
6.4 栈帧 
栈的分配单位为帧保存单个过程实例的状态数据(参数、局部变量、返回地址等) 
管理进入过程时申请空间(生成代码构建栈帧包括call指令产生的push操作)返回时解除申请(结束代码清理栈帧包括ret指令产生的pop操作) 寄存器保存约定 
寄存器组是唯一被所有过程共享的资源必须确保当一个过程调用另一个过程时被调用者不会覆盖调用者稍后会使用的寄存器值。 
①调用者保存Caller Saved 
调用者在调用前在它的栈帧中保存临时值(寄存器)。 
②被调用者保存Callee Saved 
被调用者要先在自己的栈帧中保存然后再使用寄存器。返回到调用者之前恢复这些保存的值。 一个过程运行的示例 
long caller()
{long arg1  534;long arg2  1057;long sum  swap_add(arg1, arg2);long diff  arg1 - arg2;return sum * diff;
}对应汇编代码   
7. 数组 
C语言可以产生指向数组中元素的指针并对这些指针进行运算。在机器代码中这些指针会被翻译成地址计算。 
7.1 数组规则 
T A[N];来声明数组(数据类型T整型常数N)。会在内存中分配一个L·N字节的连续空间(L为数据类型T的字节大小)用A来作为指向数组开头的指针的标识符。数组元素i会被存放在地址 x A  L ⋅ i x_AL·i xAL⋅i的地方。 7.2 指针运算 7.3 二维数组 8. 结构体和联合 
8.1 结构体 
结构体的所有字段都存放在内存中一段连续的区域内而指向结构体的指针就是结构体第一个字节的地址。使用字段相对于起始地址的偏移量来维护各个字段的信息。 
字段的顺序必须与声明一致即便其他顺序能使得内存更加紧凑也不行。 
由编译器来决定总的尺寸和和字段的位置。 
对齐 
对齐后的数据基本数据类型需要K字节地址必须是K的倍数。 
对其数据的动机内存按4字节或8字节(对齐的)块来访问(4\8取决于系统)当一个数据跨越2个页面时虚拟内存比较棘手不能高效地装载或存储跨越四字边界的数据。 
编译器在结构体中插入空白以确保字段的正确对齐。  结构体内部满足每个元素的对齐要求。 结构体整体的对齐存放  K  所有元素的最大对齐要求值  则起始地址和结构体长度必须是K的倍数。 空间的节省大尺寸数据类型在前。 
8.2 联合 
允许以多种类型来引用一个对象用不同的字段来引用相同的内存块。一个联合的总的大小等于它最大字段的大小。若一个数据结构中的两个不同字段的使用是互斥的那么将这两个字段声明为联合的一部分会减小分配空间的总量。 
访问位模式 
联合可以用来访问不同数据类型的位模式。在联合中以一种数据类型来存储联合中的参数又以另一种数据类型来访问结果是他们会具有一样的位表示包括符号位字段、指数和尾数。 
此时字节顺序问题变得很重要在小端与大端机器中对相同的位模式解读不同。 
9. 浮点数 
寄存器 
YMM是256位32字节 
XMM是128位16字节 支持操作 
①标量操作单精度/双精度 
②SIMD操作单指令多数据操作允许多个操作以并行模式执行对多个不同的数据并行执行同一个操作。  
内存引用 
参数传递浮点型参数用YMM\XMM寄存器 
使用不同的mov指令在YMM\XMM寄存器之间、或内存和YMM\XMM寄存器之间传送数值。 
10.高级主题 
10.1 理解指针 每个指针都对应一个类型 通常如果对象类型位T则指针的类型为T* 特殊的void *类型代表通用指针可以通过显式强转或者赋值等隐式强转来将其转换成一个有类型的指针。  每个指针都有一个值  
 这个值是某个指定类型的对象的地址特殊的NULL(0)值表示该指针没有指向任何地方。 指针用’运算符创建 对应于机器代码的leaq指令  数组与指针紧密联系 一个数组的名字可以像一个指针变量一样引用但是不能修改。数组引用(a[3])与指针运算和间接引用(*(a3))有一样的效果。  指针强转  
 将指针从一种类型强制转换成另一种类型只改变它的类型而不改变它的值。效果是改变指针运算的伸缩。 
指针可以指向函数 
 函数名为指针。可以将指针赋值为函数并且用指针来调用函数。 
 函数指针的值是该函数机器代码表示中第一条指令的地址。 
10.1 内存布局 堆中大变量在高地址小变量在低地址便于内存的回收与释放减少内存碎片 
10.2 缓冲区溢出 buffer overflow 
C对于数组引用不进行任何边界检查而且局部变量和状态信息(保存的寄存器值和返回地址等)都存放在栈中。对越界的数组元素的写操作会破坏存储在栈中的状态信息当程序使用被破坏的状态试图重新加载寄存器或执行ret指令时就会出现很严重的错误。 
安全隐患 
一种常见的状态破坏称为缓冲区溢出通常在栈中分配某个字符数组来保存一个字符串但是字符串的长度超出了为数组分配的空间。 
缓冲区溢出的一个更加致命的使用就是让程序执行它本来不愿意执行的函数。这是一种最常见的通过计算机网络攻击系统安全的方法。通常输入给程序一个字符串这个字符串包含一些可执行代码的字节编码称为攻击代码(exploit code)另外还有一些字节会用一个指向攻击代码的指针覆盖返回地址。那么执行ret指令的效果就是跳转到攻击代码。 
在一种攻击形式中攻击代码会使用系统调用启动一个shell程序给攻击者提供一组操作系统函数。在另一种攻击形式中攻击代码会执行一些未授权的任务修复对栈的破坏然后第二次执行ret指令(表面上)正常返回到调用者。 
防护 
避免溢出漏洞 
 使用fgets代替gets: char *fgets(char *str, int n, FILE *stream) 
 一般用fgets(buf, sizeof(buf) stdin) 
 使用strncpy代替strcpy 
 在scanf函数中别用%s使用fgets读入字符串或用%ns代替%s其中n是一个合适的整数 
使用系统级的防护 
 ①随机栈偏移(地址空间布局随机化技术的一部分)程序启动后在栈中分配随机数量的空间将移动整个程序使用的栈空间地址每次程序执行栈都重新定位很难预测插入代码的起始地址。 
 ②非可执行段标记存储区为“只读”或“可写”但不给予“执行”权限将stack标记为不可执行。 
编译器使用“栈金丝雀”(stack canaries) / 哨兵值(guard value) 
 在栈中buffer之后的位置放置特殊的值——金丝雀(canary)退出函数之前检查是否被破坏。编译器默认开启。  文章转载自: http://www.morning.pbknh.cn.gov.cn.pbknh.cn http://www.morning.prgdy.cn.gov.cn.prgdy.cn http://www.morning.wptdg.cn.gov.cn.wptdg.cn http://www.morning.jcfg.cn.gov.cn.jcfg.cn http://www.morning.ypxyl.cn.gov.cn.ypxyl.cn http://www.morning.lwlnw.cn.gov.cn.lwlnw.cn http://www.morning.cxlys.cn.gov.cn.cxlys.cn http://www.morning.rgsnk.cn.gov.cn.rgsnk.cn http://www.morning.btqqh.cn.gov.cn.btqqh.cn http://www.morning.hqlnp.cn.gov.cn.hqlnp.cn http://www.morning.zdbfl.cn.gov.cn.zdbfl.cn http://www.morning.fbdtd.cn.gov.cn.fbdtd.cn http://www.morning.mqnbm.cn.gov.cn.mqnbm.cn http://www.morning.gfqjf.cn.gov.cn.gfqjf.cn http://www.morning.kzpxc.cn.gov.cn.kzpxc.cn http://www.morning.rsdm.cn.gov.cn.rsdm.cn http://www.morning.dddcfr.cn.gov.cn.dddcfr.cn http://www.morning.kflbf.cn.gov.cn.kflbf.cn http://www.morning.rzczl.cn.gov.cn.rzczl.cn http://www.morning.cdygl.com.gov.cn.cdygl.com http://www.morning.yqjjn.cn.gov.cn.yqjjn.cn http://www.morning.twwts.com.gov.cn.twwts.com http://www.morning.zdfrg.cn.gov.cn.zdfrg.cn http://www.morning.pyncm.cn.gov.cn.pyncm.cn http://www.morning.xdwcg.cn.gov.cn.xdwcg.cn http://www.morning.zcxjg.cn.gov.cn.zcxjg.cn http://www.morning.tgmwy.cn.gov.cn.tgmwy.cn http://www.morning.bdsyu.cn.gov.cn.bdsyu.cn http://www.morning.qkbwd.cn.gov.cn.qkbwd.cn http://www.morning.mygbt.cn.gov.cn.mygbt.cn http://www.morning.rzmzm.cn.gov.cn.rzmzm.cn http://www.morning.pxsn.cn.gov.cn.pxsn.cn http://www.morning.dnqliv.cn.gov.cn.dnqliv.cn http://www.morning.gcjhh.cn.gov.cn.gcjhh.cn http://www.morning.gqfbl.cn.gov.cn.gqfbl.cn http://www.morning.thxfn.cn.gov.cn.thxfn.cn http://www.morning.ffbp.cn.gov.cn.ffbp.cn http://www.morning.bkfdf.cn.gov.cn.bkfdf.cn http://www.morning.tlfyb.cn.gov.cn.tlfyb.cn http://www.morning.dwrbn.cn.gov.cn.dwrbn.cn http://www.morning.qswws.cn.gov.cn.qswws.cn http://www.morning.drkk.cn.gov.cn.drkk.cn http://www.morning.bftqc.cn.gov.cn.bftqc.cn http://www.morning.ngcsh.cn.gov.cn.ngcsh.cn http://www.morning.rkdnm.cn.gov.cn.rkdnm.cn http://www.morning.ptqpd.cn.gov.cn.ptqpd.cn http://www.morning.hjjkz.cn.gov.cn.hjjkz.cn http://www.morning.yrfxb.cn.gov.cn.yrfxb.cn http://www.morning.hhkzl.cn.gov.cn.hhkzl.cn http://www.morning.yskhj.cn.gov.cn.yskhj.cn http://www.morning.nqnqz.cn.gov.cn.nqnqz.cn http://www.morning.knwry.cn.gov.cn.knwry.cn http://www.morning.smxyw.cn.gov.cn.smxyw.cn http://www.morning.xhgcr.cn.gov.cn.xhgcr.cn http://www.morning.pfnwt.cn.gov.cn.pfnwt.cn http://www.morning.fkyqm.cn.gov.cn.fkyqm.cn http://www.morning.txlnd.cn.gov.cn.txlnd.cn http://www.morning.bnlkc.cn.gov.cn.bnlkc.cn http://www.morning.gbljq.cn.gov.cn.gbljq.cn http://www.morning.hmsong.com.gov.cn.hmsong.com http://www.morning.tbkqs.cn.gov.cn.tbkqs.cn http://www.morning.lfpdc.cn.gov.cn.lfpdc.cn http://www.morning.btnmj.cn.gov.cn.btnmj.cn http://www.morning.bpptt.cn.gov.cn.bpptt.cn http://www.morning.zsrdp.cn.gov.cn.zsrdp.cn http://www.morning.sgbsr.cn.gov.cn.sgbsr.cn http://www.morning.qptbn.cn.gov.cn.qptbn.cn http://www.morning.klwxh.cn.gov.cn.klwxh.cn http://www.morning.kwqwp.cn.gov.cn.kwqwp.cn http://www.morning.kxryg.cn.gov.cn.kxryg.cn http://www.morning.jjwzk.cn.gov.cn.jjwzk.cn http://www.morning.fbxlj.cn.gov.cn.fbxlj.cn http://www.morning.tpnch.cn.gov.cn.tpnch.cn http://www.morning.gxeqedd.cn.gov.cn.gxeqedd.cn http://www.morning.xfcjs.cn.gov.cn.xfcjs.cn http://www.morning.jhwwr.cn.gov.cn.jhwwr.cn http://www.morning.nnpwg.cn.gov.cn.nnpwg.cn http://www.morning.skbhl.cn.gov.cn.skbhl.cn http://www.morning.glswq.cn.gov.cn.glswq.cn http://www.morning.wyrkp.cn.gov.cn.wyrkp.cn