教材《汇编语言》第二版 王爽
第二章:寄存器
· CPU中,用16位来存储一个字。高8位存放高位字节,低8位存放低位字节。
· 内存存储中,内存单元是字节单元(1单元=1字节),则一个字要用两个地址连续的内存单元存放。
· 内存存储中,高位字节,和低位字节是相对的,指令指向的是低位字节。
· 字单元,即存放一个字型数据(16位=2字节)的内存单元,由两个地址连续的内存单元组成。
· 8086CPU中有一个DS寄存器,通常用来存放要访问数据的段地址。
o MOV指令的几种种功能:
将数据直接送入寄存器 mov ax,1000H
o 将一个寄存器中的内容送入另一个寄存器 mov ax,bx;mov ds,ax
o 将一个内存单元中的内容送入寄存器 mov ax,[...]
o 将寄存器中的内容送入内存单元 mov [...],ax
o ...
· “[...]”表示一个内存单元,“[...]”中的内容则表示内存单元的偏移地址。
· 8086CPU中,不能给DS寄存器直接赋值,需要通过通用寄存器间接赋值,如“段地址-->通用寄存器-->DS寄存器”。
· add指令表示相加,sub指令表示相减。
· [address]便是一个偏移地址为address的内存单元。
· mov、add、sub是具有两个操作对象的指令。jmp是具有一个操作对象的指令。
· 栈是一种具有特殊的访问方式的存储空间,它的特殊性就在于,先进后出的特性。
· 8086CPU提供了入栈和出栈指令,最基本的两个是PUSH(入栈)和POP(出栈)。
· 8086CPU的入栈和出栈操作都是以字(2字节)为单位进行的。
· 8086CPU中,有两个寄存器,段寄存器SS和寄存器SP,栈顶的段地址存放在SS中,偏移地址存放在SP中。
· 任意时刻,SS:SP指向栈顶元素。
· PUSH入栈时,SP=SP-2(1字),栈顶从高地址向低地址方向增长,出栈时则SP=SP+2.
· 当栈为空时,栈中没有元素,也就不存在栈顶元素,所以SS:SP只能指向最底部单元下面的单元。
· 8086CPU不能保证我们对栈的操作不会超界,它只知道栈顶在何处(有SS:SP指示),并不知道这个栈有多大。
· push和pop指令可以有如下形式:
· push 寄存器
· pop 寄存器
· push 段寄存器
· pop 段寄存器
· push 内存单元
· pop 内存单元
21. 请灵活,仔细运用CS:IP(指令),DS:[...](数据),SS:SP(栈)
· 对于数据段,将它的段地址放在DS中,用mov,add,sub等访问内存单元的指令时,CPU就将我们第一的数据段内容当成数据来访问。
· 对于代码段,将它的段地址放在CS中,将段中的第一条执行的指令的偏移地址放在IP中,这样CPU就会执行代码段中的指令。
· 对于栈段,将它的段地址放在SS中,将栈顶单元的偏移地址放在SP中,这样CPU在需要进行栈操作时,比如push,pop指令时,就将栈段当成栈空间来用了。
第四章
MASN中:
mov ax,0ffffh
mov ds,ax
mov bx,1
mov al,[bx]或者
mov ax,0ffffh
mov ds,ax
mov al,ds:[1]
2.Loop指令
assume cs:code
code sement
mov ax,2
mov cx,3
s: add ax,ax
loop s
code edns
end
其中s为loop的标号,代表一个地址,它标识了一个地址,该表示可以随意命名,要与loop XX 相同即可;cx为循环次数,当执行loop s时,cx会减1,直到cx=0才停止循环;
loop s代表,当cx不为0时,运行到这时会找到s标识地址开始执行。
3.在汇编源程序中,数据不能以字母开头,可以在开头多加一个0.
4.在进行数据计算式,要考虑到运算结果是否会超过寄存器的范围
5.用于显式锝指明内存单元的段地址的"ds:","cs:","ss:","es",,在汇编中称为段前缀。
6.在一般PC机中,0:200~0:fff之间的256个字节空间一般都是安全的。
2: 【在代码段中使用数据】方法如同在代码段中使用数据一样(入口标识符前定义),如果定义 8 个字单元(0~15)数据,和 8 个字单元栈(16~31),因为栈的初始化是空的一堆 0,所以 sp 指向的栈顶+2也就是栈的下一字节。
3: 【包含多个段的程序】
【assume cs:a,ds:b,ss:c】【mov ax,b mov ds,ax】
第七章 更灵活 定位内存地址的方法
1: 【AND 和 OR】AND 和 OR 的运算
补充:【XOR 和 NOT】XOR 异或逻辑运算:XOR 操作数一,操作数二,如果两个数相等为假,两个书不想等为 1。NOT 非逻辑运算,NOT 操作数一,对操作数取反吧= =。
2:【ASCII】
128 位标准 ASCII 码,及扩展 ASCII 码。
3: 【字符形式给出的数据】
【db ‘A’】定义的字节数据
【dw ‘A’】定义的字数据,A 是字型的。
【db 1,2,3】定义的 1,2,3 是字节数据。
4: 【SI 和 DI】
SI 和 DI 十六的寄存器,作用和 BX 相似但不可以拆分成两个 8 位寄存器
5: 【bx+idate】
偏移地址的组合,灵活运用。比如【二维数组】
6: 【bx+si】
比如【嵌套循环】,由于循环 LOOP 与 CX 绑定,所以进入第二层循环时会覆盖第一层循环导致程序错误。
这时栈便发生了他的作用,先进后出,可以用栈 PUSH 外层数据后进入内层循环,内层循环后在用 POP 恢复外层数据。
7: 【bx+si+idata】
......
注意:[DI+SI]不可以用这种表现方式,BX 是女的,SI 和 DI 是男的。[SI+DI]等于搞基。
1: 【BX DI SI BP】
BP 默认段地址在 SS 中。
2: 【数据处理位置的表达】
1:立刻数
直接包含在机器码中的数据(执行前在 CPU 缓冲器中)
2:寄存器
指令要处理的数据在寄存器中
3:段地址×16+偏移地址指令要处理的数据在指定的内存中
以上三种数据位置表达方式的翻译。
3: 【寻址方式】
1:直接寻址 mov ax,[0]
2:寄存器间接寻址 mov ax,bx
3:寄存器相对寻址 mov ax,[bx+1]
4:基址变址寻址 mov ax,[bx+si]
5 相对基址变址寻址 mov ax,[bx+si+idate]
4: 【指令要处理的数据是多长】
1:在寄存器位数的情况下
2:在没有寄存器位数的情况下
push AX栈一次推进 2 字节 (sp-2).......
3:ptr 指令制定访问单元是 byte 还是 word
mov byte ptr ds:[10],1 ds:[10]01
mov word ptr ds:[10],1 ds:[11]01 ds[10]00
5: 【寻址方式的综合利用】
模拟高级语言的数组及结构体
6: 【div 指令】
纠结的除法指令= =,被除数放在 AX 或 AX 和 DX 中。
div 除数(寄存器,或内存单元)
被除数÷除数=商...余数
除数是 8 位时,AX 放的是被除数,div 后...AL 放的是商,AH 放的是余数(AX)=(AX)/(BL)。
除数的 16 位时,AX 和 DX 结合成被除数。(ax)(dx)=(DX×10000h+ax)/bx
DX 乘 10000H 代表的是高十六位,变成 32 位十六进制后面加 4 个 0 和 段地址×16(10H)相似。
DX=DE45 AX=1111 组合 DE45(16 位)×10000H=DE450000【变成 32 位了。1 个十六进制换 4 个二进制】DE450000+AX(1111)=DEA51111(组合完成的被除数)
7: 【dd】
双字 dd,32 位(4 个字节)
8: 【dup】
简洁方便快速安全常用省事懒人必备。
db 5 dup(0)等于 db 0,0,0,0,0,
db 3 dup(a,b,c)等于 db a,b,c,a,b,c,a,b,c
9: 【实验】纠结的代码,核心是用到【bx+idate+si(di)】,div,一个字节一个字节的放数据。
mov al,[bx+0]
mov es:[si+0],ax
mov al,[bx+1]
mov es:[si+1],ax
mov al,[bx+2]
mov es:[si+2],ax
mov al,[bx+3]
mov es:[si+3],ax 10909050 是双字(四字节),BX 主管双字节偏移,一次偏四字节(年份收入)。SI 主管大循环填充结果的。一次偏 16 字节
mov ax,16[bx]
mov es:[si+5],ax
mov dx,18[bx]
mov es:[si+7],dx 偏移数据一样,用常量改地址
mov ax,32[di]
mov es:[si+10],ax di 是单节,一偏移一字,主管每次循环(人数)
div word ptr es:[si+9] 平均后的结果,除数 word 定义 16 位,结合上面的 dx 和 ax
mov es:[si+13],ax
结构类型,改地址处理下一行,改变量处理元素。
第九章:转移指令的原理
1: 【转移指令】
短转移 jmp short 标号
汇编翻译成机器码是两字节,比如 EB03 向下偏移 3 个字节, 向上转-位移字节向下转+位置字节(FF 距离-128~127)。实现的是段内短转移。
近转移 jmp near ptr 标号
和短转移相似,机器码是三字节,××FFFF(上下距离)可以在段内任何地方转移
远转移 jmp far ptr 标号
段间转移机器码是五字节,比如 EA0B01BD0B,除了EA 高字对应 CS 低字对应 IP,高低字节对应,所以转移到 CS:IP B0BD:01B0。
条件转移 jcxz 标号
可以理解成如果 CX 等于 0,执行跳转的短转移。
转移地址在寄存器中
jmp ax(十六位) 段内转移,IP 偏移地址等于 AX转移地址在内存中
jmp word ptr ds:[0] 两字节,段内转移,偏移地址在内存中。
【不是跳转到 ds:[0]中,而是取出 ds:[0]内存中的值进行跳转,在一个段之间跳转】
jmp dword ptr IP:CS 四字节,段间转移。和远转移相似高低对应。
2: 【offset】
Mov ax,offset s,把标号 s 的地址给 ax。段内两字节。
第十章:call 和 ret 指令
1: 【ret 和 retf】
Ret 把栈中的数据取出放入 ip 相当于 pop ip
Retf 把栈中的数据取出放入 cs 和 ip pop ip pop cs
40: 【call 标号】
call 标号 把当前地址存入栈,然后跳到标号处(近转移 2 字节,内存中存放的是位移字节,和 jmp 原理相似)
call far ptr 标号 把当前地址存入栈,然后转到标号处(远转移 4 字节,内存中存放的是跳转地方的段地址和偏移地址)
第十一章:标志寄存器
补充: 【补码】
正数补码等于源码,负数补码等于正数补码取反加 1,为了弥补-0 的错误。
1: 【标志寄存器和标志】
标志寄存器 flag 和普通寄存器不同,它是按位起作用的(0~15 位)。8086 中 1 3 5 12 13 14 15 这几位是空的。比如第六位的 zf 标志代表运算结果是否为 0,是 0 zf 标志为真(1)否则为假。
【ZF】结果是否为零。是零为 1
【PF】判断结果是否偶数
【SF】判断最高位是否为 1,如果是一当作有符号数则为负数
【CF】无符号数,是否进位或借位,add al,al al=98h al=30h,进位了...
mov al,97h sub al,98h 不够减于是 97h 借了以为变成 197h-98h
CF 的衍生 adc 和 sbb,adc 操作对象 1,操作对象 2 +CF,这里的 CF 是上一次运算是否进位。sbb 作对象 1,操作对象 2 -CF 这里的 CF 是上一次运算是否借位。adc 与 sbb 皆从低位到高方便进位和借位,可以实现大数相加减。
例如:54AB 003BH+89A CD23H
mov bx,54abh
mov ax,003BH
add ax,CD23H
adc bx,089ah
【OF】有符号数,判断是否溢出。
2: 【cmp 与(jump)】
cmp ax,bx[1]:无符号数比较(ZF,CF)无符号数看借位
ZF=0 AX≠BX
ZF=1 AX=BX
CF=0 AX>=BX
CF=1 AX<BX
CF=0 和 ZF=0 AX>BX
CF=1 或 ZF=1 AX<=BX
(总结,看到 zf 考虑是否等于,看到 cf 考虑是否小于,cf 等于 0 时并且考虑等于 0 未借位)
[2]:有符号数比较(ZF,OF,SF)有符号数看溢出,同上两者有些相似。
ZF=0 AX≠BX
zf=1 ax=bx
ZF=1 或 SF=1 OF=0 ax<=bx(OF 溢出如果 1,正常逻辑的反结果)ZF=1 或 SF=0 OF=0 AX>=BX
ZF=1 或 SF=1 OF=1 ax<=bx(OF 溢出如果 1,正常逻辑的反结果)ZF=1 或 SF=0 OF=1 AX<=BX
ZF=0 SF=1 OF=1 AX>BX
ZF=0 SF=0 OF=0 AX>BX
ZF=0 SF=0 OF=1 AX<BX
ZF=0 SF=0 OF=1 AX<BX
(上面的逻辑没有验证,总结遇到 of 值等于 1 其他逻辑的反结果是正确的)
【总结的总结:用逻辑判断,记这些不如看到位寄存器的值来得快,主要是 cf 等于 0时考虑结果是否为 0,还有 of 溢出正常逻辑的反结果。总结一段,无符号看 cf zf cf 注意 0zx 看是否等 0。有符号看 of sf zf,zf 同上 of 反结果 sf 结果是否为负。】
[3]cmp 和各种(jump)的结合(这些检测的是标志寄存器位)
je ZF 是都等于 1
jne ZF 不等于 1
ja 仅检测标志位的值,详细百度= =
jna ==
jb ==
jnb 同上
3: 【df】
df 方向传递,当 df=0 时 si+1,di+1(cls 指令设置,正方向传递)。当 df=1 时 si-1 di-1(std 设置,反方向传递)与 cx,rep,movsb(movsw)配合可以实现字符串传递。
rep 循环 cx 次后面的语句一般是 movsw。
movsw 之类的,相当于 mov ax,ds:[si+0] mov es:[di+0],ax。
原文地址:http://www.cnblogs.com/guidovanrossum/p/3810035.html