这个总结先在wps上已经写完放很久了。之前由于考试,没来得及放上来。现在一次性都放上来吧~
刚看完汇编,由于是借学校的书,所以就把关键知识点写在博客上了.
参考的是richard blum的<汇编语言程序设计>,看豆瓣上面分数蛮高的.
主要平台是linux下的AT&T汇编..
我学汇编主要是想可以看懂汇编代码的意思.其实所谓优化也不过是调调代码顺序,用点比较特殊的指令,如果不是很有经验的话,可能人来优化的还不如编译器..
我就把汇编当作以后学新语言了解编译器在干什么的一个工具就可以了.
嗯...下面说正文
第一部分主要说明的是对汇编的介绍和编译调试,所以我就简单介绍一下.重点在编译和调试
计算机是如何执行程序的?
第一章一开始就提到了,程序是纯二进制的.是CPU通过时序逻辑将二进制的高低电平读入,然后根据二进制码来执行相关操作的.这里的指令码格式学过计算机组成原理的估计就可以不用说了吧.简单来说就是指令的一部分是操作的编码,一部分是数的编码.
这里提到一点比较重要,就是指令前缀(操作的编码一部分)的锁定前缀.原来还疑惑多处理器是怎么做到对共享内存区的原子操作的,现在来看就是这里的原因了.CPU已经提供了这种多CPU共享内存的保障.(几个月后,看了Linux源码,发现原来自己接触过这个东西...所有锁都是用的这个方式,锁定总线)
程序是如何生成可执行文件的?
顺带讲一讲,很多大学生学C的时候都忽略了的.估计用微软IDE编程的人都可能不太清楚(比如说我...).但是在linux下的话就很清楚了.其实编译器在编译你的源文件的时候是先生成目标代码文件再通过连接器将目标代码连接起来生成可执行文件的.如果所用到的目标代码文件是共享的话,还有动态链接这个东西,当然我们如果没做过大项目的话,应该用的都是静态连接.即把程序一次性全部都放到内存.动态连接则是一部分一部分的连接.
汇编程序的组成有哪些?
1.数据段
2.Bss段
3.文本段(代码段)
数据段和bss段都是用来存放数据的区域.
文本段就是代码段,就是你自己写的代码.
注意,其实对于gcc有时候并不是将bss段当作存放全局变量的区域.而是放在.data段中.
百度的解释是:BSS存放的是未初始化的全局变量和静态变量,数据段存放的是初始化后的全局变量和静态变量。
实际上我在linux下测试之后发现,全局变量声明的时候是用的.comm声明的,并且没有看到.bss的声明。我想现在的汇编器应该默认会是.bss段了吧。
汇编语言有标准吗?
汇编语言实际上是没有标准的.基本根据汇编器来.所有你写的都是助记符,也就是mov,sub之类的都是汇编器提供的.所以汇编器就很重要.很多高级语言的特性都依赖于汇编器的命令.
(几个月后来看也不能说没有标准,默认的都会支持基本的C编译需要的指令)
Intel和AT&T汇编差别大吗?
由于之前怕难,就学了16位汇编,现在看intel汇编和AT&T汇编差别也不是太大..只是AT&T汇编编写比intel的繁琐一些.,绝大部分都是相似的.资料方面也基本相同.linux有这么方便的开源优势.建议初学者直接选AT&T.而且还能熟悉gdb调试,这对之后调试其他语言都是有经验累积的.当然你说你只想在windows下编程那还是去学intel的吧.
CPU是顺序执行你程序里的二进制代码吗?
这个我之前也觉得除了cache可以缓存一下其他没什么.但是学了汇编才知道intel还真是很NB啊..除了缓存还有
1.指令的预取和解码(计算机组成原理里面的流水线技术?)
2.分支预测
这个很NB啊,可以根据你运行的if ,switch各个单元选中的概率来预读.
当然还有函数调用和循环这之类的跳转指令的优化.
主要包括3种技术
深度分支预测
动态数据流分析
推理行执行(感觉个个都是碉堡的节奏啊...)
3.乱序执行引擎
这个东西一听名字好奇怪,但其实就是通过几个缓冲区,来改变指令的顺序.让指令更快的执行
4.退役单元
就是接手乱序执行引擎送出来指令送去执行,然后监视执行的情况.并且将指令调整到正确的顺序..(高端技术..只能了解了解..)
通用寄存器有哪些?
寄存器简单的来说就是CPU中存储处理数据的一个小的触发器(数电的内容啊!),速度很快,所以用于指令的操作(指令绝大部分都要用到寄存器的,也有简单的指令不用.比如nop)
EAX | 操作数和结果数据的累加器 |
EBX | 指向数据内存段中的数据的指针 |
ECX | 字符串和循环操作的计数器 |
EDX | I/O指针 |
EDI | 用于字符串操作的目标的数据指针 |
ESI | 用于字符串操作的源的数据指针 |
ESP | 堆栈指针 |
EBP | 堆栈数据指针 |
敲了一遍回忆了好久后面的知识点..写总结还是得多写啊.
通过段寄存器访问系统内存的方式有哪些?
这个不是组成原理里面的一大堆寻址方式..而是内存使用的方式...组成原理中寻址方式是针对汇编指令的。
1.平坦内存模式
2.分段内存模式
3.实地址模式
平坦内存模式:就是将所有内存都看成线性连续的地址空间.即段基址为0..主流操作系统都是这个模式.
分段内存模式:就是操作系统课程里面的,按逻辑来给指令分段.顺带一说,教科书真的是该看国外的啊.我课本上面还写着分页式管理内存空间的操作系统不能动态连接..其实linux就是分页式的操作系统,一样可以实现动态连接.操作系统实现基本都是靠的设计者编码..哪有不能的呢?只有想不到的.
不过单就汇编的话,这些寄存器应该多用于控制堆栈空间.也就是保存数据的地方,然后通过偏移量+堆栈基址指针的方式来找到对应的变量存储位置.顺带一说AT&T的堆栈空间貌似都是从高地址开始向低地址延伸的.所以偏移量通常为负数
实地址模式:所有段寄存器都指向零线性地址,并且都不会被程序改动.所有指令码,数据元素和堆栈元素都是通过他们的线性地址直接访问的.或者还是存放C语言中常量字符串的地方?这个零线性地址google和百度都没有搜索相关结果.(几个月后来看,感觉实地址模式只是存在于8086中的..感觉翻译也有问题.)
CS | 代码段 |
DS | 数据段 |
SS | 堆栈段 |
ES | 附加段指针 |
FS | 附加段指针 |
GS | 附加段指针 |
什么是指令指针寄存器?
其实就是计算机组成原理里面的PC寄存器,每次将所指向的指令取出来执行.如果要预取的话就不是线性的取了..不过一般不用管这个.一般和CS+EIP就是所指向的位置.CS是段位置
EIP是偏移量.
什么是控制寄存器?
用于确定处理器的操作模式.这估计只有写操作系统的人才用得到的吧
CR0 | 控制操作模式和处理器状态的系统标志 |
CR1 | 当前没有使用 |
CR2 | 内存页面错误信息 |
CR3 | 内存页面目录信息 |
CR4 | 支持处理器特性和说明处理器特性能力的标志 |
CR3就是所谓的页目录地址。
不能直接访问控制器寄存器中的值,但是可以将数据传给通用寄存器,然后用通用寄存器的值来赋给控制寄存器.
标志表
CF | 0 | 进位标志 |
PF | 2 | 奇偶校验标志 |
AF | 4 | 辅助进位标志 |
ZF | 6 | 零标志(结果为0,不是除零的标志) |
SF | 7 | 符号标志 |
OF | 11 | 溢出标志 |
TF | 8 | 陷阱标志 |
IF | 9 | 中断使能标志 |
IOPL | 12和13 | I/O特权级别标志 |
NT | 14 | 嵌套任务标志 |
RF | 16 | 恢复标志 |
VM | 17 | 虚拟8086模式标志 |
AC | 18 | 对准检查标志 |
VIF | 19 | 虚拟中断标志 |
VIP | 20 | 虚拟中断挂起标志 |
ID | 21 | 识别标志 |
1.第一部分状态标志(OF之上)
意思基本都很明确
2.第二部分控制标志
表中没有显示,只要是一些指令会自动操作指针,然后自动增减
DF =1,递减
DF=0递增
3.第三部分系统标志
陷阱标志主要是启动单步模式.也就是说在运行程序的时候可以一条指令一条指令的执行.也就是同志们熟悉的调试.以前还以为是通过程序来控制的.现在才发现是在CPU级别上来控制的.
中断使能标志.用于描述如何响应外部接受到的信号(估计就是外部中断).
I/O特权字段标明当前正在运行的任务的I/O特权级别.
嵌套任务标志控制.当前正在运行的任务是否链接到前一个执行的任务.可能是用来恢复中断的吧(中断结束后是结束程序,还是继续程序).
恢复标志.调试模式中,如何处理响应异常.
至于后面虚拟的几个标志我就不说了.win7都已经不支持8086的16位工作模式了.
嗯,汇编的基本介绍已经结束了.