教材是王爽《汇编语言》第二版
第一章 基础知识
- 机器语言是计算机硬件能直接执行的语言,也就是一系列二进制数字101010101001
- 汇编语言也是计算机硬件能“间接”执行的语言,他是机器语言更便于程序员书写和记忆的表现形式,所以需要汇编语言到机器语言需要编译器转一下
- 每一个CPU都有许多管脚,管脚连接着3种总线,分别是地址总线、数据总线和控制总线。3种总线的宽度(也就是总线有多少位)代表了CPU3个方面的性能:
- 地址总线代表了CPU的寻址能力
- 数据总线代表了一次能传输的数据量
- 控制总线负责传输指令
- 编程中常说的内存其实是假想的逻辑存储空间,他是由一个个真实的物理内存比如RAM、显存、各种接口卡的ROM组成的,再给这个逻辑存储空间从0开始到最大寻址(由地址总线宽度决定)进行编号就有了低地址内存和高地址内存
第二章 寄存器
1. 通用寄存器:AX,BX,CX,DX
教材中是用的8086CPU,也就是说寄存器是16位的(关于本教材用的8086CPU,地址总线是20位的,数据总线是16位的,内存是8位的),而且为了兼容以前的8位寄存器,这四个寄存器每个都可以拆成高低两个独立寄存器单独使用,所以8086CPU可以读写的数据尺寸有两种,一种是8位的Byte,一种是16位的word(字)
比如,假设此时ax值为005CH,执行语句add al,93H,虽然5CH+93H=158H,但是超出的1并不会存到到ah中去,也就是说此时ax值为0058H,因为此时al是作为一个独立寄存器使用的,与ah无关
2. 物理地址
- 8086CPU的地址总线有20位,但寄存器只有16位(注意这里不是数据总线),所以为了能访问内存的全部地址,寻址方式为 物理地址=段地址 * 16+偏移地址
- 也就是说,数据总线一次传两个值,一个值为段地址,一个值为偏移地址,这里16是怎么来的呢,其实就是2的20次方除以2的16次方的结果
- 段地址的物理地址必须是16的倍数
- 段地址的长度最大为2的16次方也就是64KB(算2的多少次方时记住2的10次方就是1024)
3. CS和IP
CS代码段寄存器(段寄存器还有三个:DS、SS、ES)和IP指令指针寄存器是8086中两个最关键的寄存器,也就是说,任意时刻,CPU将CS:IP指向的内容当作指令执行
8086启动时CS=FFFFH,IP=0000H,也就是说执行的第一条指令是FFFF:0000(物理地址为FFFF0H)
4. 修改CS和IP的值
修改前面通用寄存器AX等时可以用转移指令mov,但是CS和IP只能用传送指令jmp,比如jmp AAAA:BBBB的意思就是CS=AAAA,IP=BBBB;也可以单独修改IP的值,但是必须用寄存器间接来修改,比如jmp bx的意思就是把BX的值赋给IP
第三章 寄存器(内存访问)
1. 段寄存器不能直接赋值,要通过其他寄存器来中转;也不能做加减运算
2. 关于数据和指令
首先数据和指令其实都是以101010的二进制形式存放在内存中,只是CPU规定了CS+IP(段地址+偏移地址)指向的内存当作指令来执行,DS+偏移地址指向的内存当作数据
3. 栈
栈就是一段具有特殊访问方式的内存空间,这种特殊方式就是LIFO(后进先出)。CPU用了两个指向栈顶地址的寄存器SS+SP来实现这种数据结构,但是对栈大小的把控也就是栈越界的问题需要我们自己去控制和注意
- 入栈:push ax
- 第一步:sp - 2
- 第二步:把ax的内容放入[ss+sp] 指向的内存
- 出栈:pop ax
- 第一步:把[ss+sp] 指向的内存中的内容放入ax
- 第二步:sp + 2
push和pop的实质就是内存传送指令
4. 小知识:对寄存器清零用sub ax,ax比mov ax,0要好,因为前者只占2字节机器码,后者占3字节机器码
5. 对段的理解:
![](https://img.haomeiwen.com/i1477016/6a929d1d3fe012bb.png)
![](https://img.haomeiwen.com/i1477016/d027103e8adae354.png)
6.一个奇怪的地方
mov ss,ax
mov xx,xx
只要执行了第一条指令(给栈段寄存器ss执行mov操作),那么下一条指令会马上紧接着执行(这是因为中断机制,这里暂不详述),而且ss+sp指向的栈段的内容会发生改变,这是为什么呢?我们发现这里面有cs值、ip值、ax值(这个容易看出来),还有bp值(00 00),还有flag的值(这个我用肉眼是看不出来了。呵呵,就是那个一排英文字符)。在讲内中断这章时,你就明白了。t命令实际是引发了单步中断,执行中断例程时,CPU会将一些中断例程使用的的寄存器变量自动压栈到栈中,此例中就包括了上述的寄存器变量的值。
第四章 第一个程序
1.一段汇编代码的完整格式
assume cs:code
code segment
...
mov ax,4c00h
int 21h
code ends
end
Debug要用p命令执行int 21h来表示程序结束
2.汇编程序从写出到执行的过程
![](https://img.haomeiwen.com/i1477016/357dcf581bdb67ae.png)
3.连接的作用
![](https://img.haomeiwen.com/i1477016/886b096a6380194d.png)
4.Debug加载汇编exe文件后三个值得关注的寄存器
-
cx存放着代码大小,以字节为单位
- ds存放着程序所在的内存区的段地址
-
cs的值在ds的基础上加10h(物理地址加了100h,也就是256字节),这段区域是存放着PSP
第五章 [BX]和loop指令
1.Loop指令
loop就是汇编中的循环,循环次数用寄存器cx来控制
![](https://img.haomeiwen.com/i1477016/c8160f43c27bfd75.png)
2.Debug中用p命令来快速执行完一个Loop,用g+偏移地址快速执行到某一行
3.一段安全的内存空间
0:200 2ff这段256字节的空间很安全适合我们学习编码
![](https://img.haomeiwen.com/i1477016/a073721224cb64d1.png)
第七章 更灵活的定位内存地址的方法
1.and和or指令
- and可将操作对象相应位设为0
- or可将操作对象相应位设为1
比如:
将al的第6位设为0的指令为: and al,10111111b
将al的第6位设为1的指令为: or al,01000000b
2.字母大小写转换的另一种方式
除了根据ASCII值得知“小写字母=大写字母+20H”这个规律以外,从小写字母和大写字母ASCII码的二进制形式来看,除了第5位不一样其余位数全部相同,小写字母第5位为1,大写字母第5为0,所以可以运用and和or指令来快捷转换大小写
3.寻址方式
- [bx/si/di + idata]
- [bx + si/di]
- [bx + si/di + idata]
4.栈的应用
![](https://img.haomeiwen.com/i1477016/120a7a85c7920fa9.png)
5.二重循环
里层循环开始前入栈cx,里层循环结束出栈cx
![](https://img.haomeiwen.com/i1477016/4cfe915fec3d4f45.png)
网友评论