第3章 寄存器(内存访问)
3.1 内存中字的存储
●CPU中用16位寄存器来存储一个字,高8位存放高位字节,低8位存放低位字节
●字单元即存放一个字型数据的内存单元,由两个地址连续的内存单元组成;高地址内存单元中存放字型数据的高位字节,低地址内存单元中存放字型数据的低位字节
●将起始地址为N的字单元称为N地址字单元,比如:2地址字单元由2、3两个内存单元组成
3.2 DS和[address]
CPU要读写一个内存单元的时候,必须先给出这个内存单元的地址,在8086PC中,内存地址由段地址和偏移地址组成。8086CPU中有一个DS寄存器,通常用来存放要访问的数据的段地址。比如我们要读取10000H单元的内容,可用以下程序段:
mov bx,1000H
mov ds,bx
mov al,[0]
上面的三条指令将10000H(1000:0)中的数据读到al中。
下面详细说明指令的含义:
mov al,[0]
前面我们使用mov指令,可完成两种传送:(1)将数据直接送入寄存器;(2)将一个寄存器中的内容送入另一个寄存器。
也可以使用mov指令将一个内存单元中的内容送入一个寄存器中。mov指令格式为: mov 寄存器名, 内存单元地址。
“[]”表示一个内存单元,“[0]”中的0表示内存单元的偏移地址,段地址默认放在ds中。
由于8086CPU硬件设计的问题,8086CPU不支持将数据直接送入段寄存器。如mov ds,1000H是非法的。所以我们得使用一个寄存器进行中转,如上例:
(1).先将段地址1000H放入中转寄存器bx中,然后再放入ds
mov bx,1000H
mov ds,bx
(2).完成数据从1000:0单元到al的传送
mov al,[0]:“[]”表示一个内存单元,“[0]”中的0表示内存单元的偏移地址,段地址默认放在ds中。
问题3.2
写几条指令,将al中的数据送入内存单元10000H中。
因为8086CPU是16位结构,有16根数据线,所以可以一次性传送16位的数据即一个字。
内存情况如图:
地址 数据 指令
10000H 23 mov ax,1000H
10001H 11 mov ds,ax
10002H 22 mov ax,[0]
10003H 66 mov bx,[2]
mov cx,[1]
add bx,[1]
add cx,[2]
分析:
指令 执行后相关寄存器内容 说明
mov ax,1000H ax=1000H
mov ds,ax ds=1000H 前两条指令的目的是将ds设为1000H
mov ax,[0] ax=1123H 1000:0处存放的字型数据送入ax
{1000:0单元存放字型数据的低八位23H(送入al),1000:1单元存放字型数据的高八位11H(送入ah),1000:0处的字型数据是1123H}
mov bx,[2] bx=6622H
mov cx,[1] cx=2211H
add bx,[1] bx=8833H 66+22=88,22+11=33
add cx,[2] cx=8833H 22+66=22,22+11=33
问题3.4
内存如图3.3所示,写出下面的指令执行后内存中的值。
地址 数据 指令
10000H 23 mov ax,1000H
10001H 11 mov ds,ax
10002H 22 mov ax,11316
10003H 11 mov [0],ax
mov bx,[0]
sub bx,[2]
mov [2],bx
分析:
指令 执行后相关寄存器或内存单元中内容 说明
mov ax,1000H ax=1000H
mov ds,ax ds=1000H 前两条指令的目的是将ds设为1000H
mov ax,11316 ax=2C34 十进制11316=十六进制2C34H
mov [0],ax 10000H 34 ax中的字型数据2C34送到1000:0处
10001H 2C ah中的高八位2CH送入高地址1000:1单元
10002H 22 al中的低八位34H送入低地址1000:0单元
10003H 11
mov bx,[0] bx=2C34H
sub bx,[2] bx=1B12H bx=bx中的字型数据-1000:2处的字型数据=2C34H- 1122H=1B12H
mov [2],bx 10000H 34
10001H 2C
10002H 12
10003H 1B
3.4.mov,add,sub指令
mov 段寄存器,寄存器<--->mov 寄存器,段寄存器
mov 内存单元,寄存器<--->mov 内存单元,段寄存器<--->mov 段寄存器,内存单元
add 寄存器,数据
add 寄存器,寄存器
add 寄存器,内存单元
add 内存单元,寄存器
sub 寄存器,数据 sub ax,bx ax = ax - bx ;
sub 寄存器,寄存器
sub 寄存器,内存单元
sub 内存单元,寄存器
3.5.数据段
例五:
写几条指令,累加数据段123B0H--123BAH中的前3个字型数据
mov ax,123BH
mov ds,ax (将123BH送入ds,作为数据段的段地址)
mov ax,0 (用ax存放累加结果)
add ax,[0] (将数据段第一个字{偏移地址为0}加到ax中)
add ax,[2] (将数据段第二个字{偏移地址为2}加到ax中)
add ax,[4] (将数据段第三个字{偏移地址为4}加到ax中)
(一个字型数据占两个单元,所以偏移地址是0,2,4)
检测点一:
在Debug中,用“d 0:0 1f”查看内存,结果如下:
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 (ds=1,此时数据段地址为:0001×10+0000(偏移量)=00010)
mov ax,[0000] AX=2662H (数据表提供的是0000:0010,此时数据段的地址为:0000×10+0010=00010)
mov bx,[0001] BX=E626H
mov ax,bx AX=E626H
mov ax,[0000] AX=2662H
mov bx,[0002] BX=D6E6H
add ax,bx AX=FD48H
add ax,[0004] AX=2C14H
mov ax,0 AX=0000H
mov al,[0002] AX=00E6H
mov bx,0 BX=0000H
mov bl,[000C] BX=0026H
add al,bl AX=000CH
●CS是告诉CPU,去哪个位置找内容当成指令去执行
●DS是告诉CPU,去哪个位置找内容当成数据被使用
●CPU要执行CS中的指令,指令用到的数据可能就存放在DS中
●你可以把数据放到CS中,但是CPU并不把它当成数据来使用,你也可以把指令放到DS中,但是CPU根本不去DS里
读指令
●任何时候,程序运行的只能是cs:ip指向的内存中的指令
3.1~3.5 小结
(1)字在内存中存储时,要用两个地址连续的内存单元来存放,字的低位字节存放在低地址单元中,高位字节存放在高地址单元中。
(2)用mov指令要访问内存单元,可以在mov指令中只给出单元的偏移地址,此时,段地址默认在DS寄存器中。
(3)[address]表示一个偏移地址为address的内存单元。
(4)在内存和寄存器之间传送字型数据时,高地址单元和高8位寄存器、低地址单元和低8位寄存器相对应。
(5)mov、add、sub是具有两个操作对象的指令。jmp是具有一个操作对象的指令。
(6)可以根据自己的推测,在Debug中实验指令的新格式。
检测点3.1
(1)在Debug中用“d 0:0 1f”查看内存,结果如下:
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 ax,[0000] AX=______ 2662H
mov bx,[0001] BX=______ E626H
mov ax,bx AX=______ E626H
mov ax,[0000] AX=______ 2662H
mov bx,[0002] BX=______ D6E6H
add ax,bx AX=______ FD48H
add ax,[0004] AX=______ 2C14H
mov ax,0 AX=______ 0000H
mov al,[0002] AX=______ 00E6H
mov bx,0 BX=______ 0000H
mov bl,[000C] BX=______ 0026H
add al,bl AX=______ 000CH
(2)mov ax,6622H
jmp 0ff0:0100
mov ax,2000H
mov ds,ax
mov ax,[0008]
mov ax,[0002]
分析:
(1)前面两条指令执行后,ds=0001H,而0001:0000等价于0000:0010H。所以,下面的指令读取的内存数据实际上是从0000:0010H开始的。