目录
前言
参考教材:王爽编著的《汇编语言》(第3版)
第1章 基础知识
1.6 存储单元
一个存储单元存储 1字节(Byte/B) = 8比特/位(bit)。
转换前 | 转换后 |
---|---|
1KB | 210B |
1MB | 220B |
1GB | 230B |
1TB | 240B |
1KB的存储器有_1024_个存储单元,存储单元的编号从__0__到__1023__。
8080、8088、80286、80386的地址总线宽度分别为16根、20根、24根、32根,则它们的寻址能力分别为:__64__KB、__1__MB、__16__MB、__4__GB。
在存储器中,数据和程序以__二进制__形式存放。
1.8 地址总线
一个CPU有N根地址线,则可以说这个CPU的地址总线的宽度为N。这样的CPU最多可以寻找2的N次方个内存单元。
1个CPU的寻址能力为8KB,那么它的地址总线的宽度为_13_位。
解答:8KB = 23 x 210B = 213B。
1.9 数据总线
8根数据总线一次可传送一个8位二进制数据(即一个字节)。
8086和80386的数据总线宽度分别是16根和32根,也就是说8086和80386一次可传送16位和32位二进制数据即2Byte和4Byte。
8080、8088、8086、80286、80386的数据总线宽度分别为8根、8根、16根、16根、32根,则它们一次可以传送的数据分别为:__1__B、__1__B、__2__B、__2__B、__4__B。
从内存中读取1024字节的数据,8086至少要读__512__次,80386至少要读__256__次。
第2章 寄存器
- 8086CPU有14个寄存器,每个寄存器有一个名称。这些寄存器是:AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW。
add ax,bx
的含义:
将寄存器 ax 中的数据与寄存器 bx 中的数据相加,结果保存在寄存器 ax 中。
2.1 通用寄存器
8086CPU的所有寄存器都是16位的,可以存放两个字节。AX、BX、CX、DX这4个寄存器通常用来存放一般性的数据,被称为通用寄存器。
2.3 几条汇编指令
add al,93H 指令产生的进位不会存储在 ah 中,add al,93H 进行的是 8 位运算。
2.7 “段地址×16+偏移地址=物理地址”的本质含义
给定段地址为0001H,仅通过变化偏移地址寻址,CPU的寻址范围为__00010H__和__1000FH__。
解答:0001H×10+0000H=00010H,0001H×10+FFFFH=1000FH。
有一数据存放在内存20000H单元中,现给定段地址为SA,若想用偏移地址寻到此单元。则SA应满足的条件是:最小为__1001H__,最大为__2000H__。
解答:偏移地址最大时,段地址最小,偏移地址最大为FFFFH,20000H-FFFFH=10001H,发现10001H除以10H除不尽,所以不能这样计算。可以换一种角度理解,当段地址为1000H时,偏移地址取FFFFH,则其内存单元为1FFFFH,而1FFFFH+1H=20000H,偏移地址仍是FFFF,则段地址应为1001H。求最大则可以直接计算。
2.10 CS和IP
CS为代码段寄存器,IP为指令指针寄存器。
在8086PC机中,任意时刻设CS中的内容为M,IP中的内容为N,8086CPU将从内存M×16+N单元开始,读取一条指令并执行。
2.11 修改CS、IP的指令
mov指令不能用于设置CS、IP的值。
jmp指令可以修改CS、IP。
- “jmp 段地址:偏移地址”——同时修改CS、IP的内容
例:jmp 2AE3:3,执行后:CS=2AE3H,IP=0003H,CPU将从2AE33H处读取指令。
- “jmp 某一合法寄存器”——仅修改IP的内容,jmp ax 可以理解为 mov IP,ax。
例:jmp ax,指令执行前:ax=1000H,CS=2000H,IP=0003H
指令执行后:ax=1000H,CS=2000H,IP=1000H
下面的3条指令执行后,CPU几次修改IP?都是在什么时候?最后IP中的值是多少?
mov ax,bx
sub ax,ax
jmp ax
解答:CPU读取mov ax,bx的时候,第一次修改IP
读取sub ax,ax的时候,第二次修改IP
读取jmp ax的时候,第三次修改IP
当执行jmp ax的时候,IP变为0,这是第4次修改
最后IP变为0
第3章 寄存器(内存访问)
3.1 内存中字的存储
我们用0、1两个内存单元存放数据20000(4E20H)。0、1两个内存单元用来存储一个字,这两个单元可以看作一个起始地址为0的字单元(存放一个字的内存单元,由0、1两个字节单元组成)。对于这个字节单元来说,0号单元是低地址单元,1号单元是高地址单元,则字型数据4E20H的低位字节单元存放在0号单元中,高位字节存放在1号单元中。同理,将2、3号单元看作一个字单元,它的起始地址为2。在这个字单元中存放数据18(0012H),则在2号单元中存放低位字节12H,在3号单元中存放高位字节00H。
3.2 DS和[address]
在8086PC中,内存地址由段地址和偏移地址组成。8086CPU中有一个DS寄存器,通常用来存放要访问数据的段地址。
在DEBUG中,用 “d 0:0 lf” 查看内存,结果如下:
0000:0000 70 80 F0 30 EF 60 30 E2-00 80 80 12 66 20 22 60
0000:0010 62 26 E6 D6 CC 2E 3C 3B-AB BA 00 00 26 06 66 88
下面的程序执行前,AX=0,BX=0,写出每条汇编指令执行完后相关寄存器中的值
mov ax,1
mov ds,ax
mov si,2
mov ax,[0000] ax=__2662__H
mov bx,[0001] bx=__E626__H
mov ax,bx ax=__E626__H
mov ax,[000C] ax=__0626__H
mov bx,[0002] bx=__D6E6__H
add ax,bx ax=__DD0C__H
提示:注意ds的设置。
解答:为什么从0000:0010开始找?因为0001:0000和0000:0010指向的都是00010H处,是等价的。
相关题目:https://blog.csdn.net/freezhanacmore/article/details/17740999
3.7 CPU提供的栈机制
8086CPU的入栈和出栈操作都是以字为单位进行的。
8086CPU中,有两个寄存器,段寄存器SS和寄存器SP,栈顶的段地址存放在SS中,偏移地址存放在SP中。任意时刻,SS:SP指向栈顶元素。
- push ax 的执行,由以下两步完成:
- SP=SP-2,SS:SP指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶;
- 将 ax 中的内容送入 SS:SP 指向的内存单元处, SS:SP 此时指向新栈顶。
- pop ax 的执行过程和 push ax 刚好相反,由以下两步完成:
- 将 SS:SP 指向的内存单元处的数据送入ax中;
- SP=SP+2,SS:SP 指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。
如果将 10000H~1000FH 这段空间当作栈,初始状态栈是空的,此时,SS=1000H,SP=0010H。
3.9 push、pop指令
push和pop指令是可以在寄存器和内存之间传送数据的。
push 寄存器 ;将一个寄存器中的数据入栈
pop 寄存器 ;出栈,用一个寄存器接收出栈的数据
push 内存单元 ;将一个内存字单元处的字入栈(注意:栈操作都是以字为单位)
pop 内存单元 ;出栈,用一个内存字单元接收出栈的数据
1.补全下面的程序,使其可以将10000H ~ 1000FH中的8个字,逆序复制到20000F ~ 2000FH中。逆序复制的含义如图所示(图中内存里的数据均为假设)。
mov ax,1000H
mov ds,ax
----补充部分----
mov ax,2000H
mov ss,ax
mov sp,0010
----补充部分----
push [0]
push [2]
push [4]
push [6]
push [8]
push [A]
push [C]
push [E]
2.补全下面的程序,使其可以将10000H ~ 1000FH中的8个字,逆序复制到20000H ~ 2000FH中。
mov ax,2000H
mov ds,ax
----补充部分----
mov ax,1000H
mov ss,ax
mov sp,0000H
----补充部分----
pop [E]
pop [C]
pop [A]
pop [8]
pop [6]
pop [4]
pop [2]
pop [0]
如果要在10000H处写入字数据2266H,可以用以下的代码完成:
mov ax,1000H
mov ds,ax
mov ax, 2266H
mov [0], ax
补全下面的3条指令,实现采用push ax 语句完成同样的功能:在10000H处写入字型数据2266H。
____mov ax,1000H__
____mov ss,ax_____
____mov sp,2______
mov ax,2266H
push ax
第4章 第一个程序
4.2 源程序
下面就是一段简单的汇编语言源程序。
assume cs:codesg
codesg segment
mov ax,0123H
mov bx,0456H
add ax,bx
add ax,ax
mov ax,4c00H
int 21H
codesg ends
end
下面对程序进行说明。
1. 伪指令
- segment和ends是一对成对使用的伪指令,它们的功能是定义一个段,segment说明一个段开始,ends说明一个段结束。
比如,程序中的:codesg segment ;定义一个段,段的名称为“codesg”,这个段从此开始 ...... codesg ends ;名称为“codesg”的段到此结束
- end是一个汇编程序的结束标记。
- assume的含义为“假设”。它假设某一段寄存器和程序中的某一个用segment…ends定义的段相关联。
5. 程序返回
mov ax,4c00H
int 21H
这两条指令所实现的功能就是程序返回。
4.8 谁将可执行文件中的程序装载进入内存并使它运行?
汇编程序从写出到执行的过程:
编程 (Edit) → 1.asm → 编译 (masm) → 1.obj → 连接 (link) → 1.exe → 加载 (command) → 内存中的程序 → 运行 (CPU)
第5章 [BX]和loop指令
- 为了描述上的简洁,我们将使用一个描述性的符号“()”来表示一个寄存器或一个内存单元中的内容。比如:
- (ax)表示ax中的内容、(al)表示al中的内容。
- 约定符号idata表示常量。
5.1 [BX]
mov ax,[bx]
功能:bx中存放的数据作为一个偏移地址EA,段地址SA默认在ds中,将SA:EA处的数据传入ax中。即:(ax)=((ds)*16+(bx))。
mov [bx],ax
功能:bx中存放的数据作为一个偏移地址EA,段地址SA默认在ds中,将ax中的数据送入内存SA:EA处。即:((ds)*16+(bx))=(ax)。
程序和内存中的情况如图所示,写出程序执行后,21000H~21007H单元中的内容。(inc bx的含义是bx中的内容加1)
mov ax,2000H
mov ds,ax
mov bx,1000H
mov ax,[bx]
inc bx
inc bx
mov