3.1 内存中字的存储
CPU中16位寄存器存储一个字:高8位在高字节,低8位在低字节。
内存中,内存单元也是字节单元,所以一个内存单元存放一个字节也就是8bit。

用此图举例。
存放的数据4E20 h存放在地址0处。其中高位字节在地址1处,低位字节在地址0处。
存放的数据0012 h是一样的。0012h存放在地址2处,高字节为00h,低字节为12h。
将起始位置为N的字单元简称为N地址字单元。
字单元:存放一个字型数据,就按照上述例子存储。
问题 3.1

(1) 20H; 地址单元应该是一个字节。
(2) 4E20H,字型数据应该是一个字单元。

(3) 12H
(4) 0012H
(5) 124EH
3.2 DS 和 [address]
CPU操作内存中的数据时。
需要指定 内存操作的 段地址:偏移地址。
所以将段地址放入ds
将偏移地址用中括号括住。
注意:8086CPU ds不能直接被赋数,要通过通用寄存器来获取.
例如:读取1000h单元的内容
mov bx, 1000h
mov ds, bx
mov al, [0]
通过bx通用寄存器将段地址存放在ds中,在中括号中使用偏移地址就可以。
问题 3.2

mov bx,1000h
mov ds,bx
mov [0],al
3.3 字的传送
因为8086CPU数据线为16根,所以能一次传16bit,2个Byte,一个字。
mov bx,1000h
mov ds,bx
mov ax,[0]
mov [0],cx
问题 3.3

ax bx cx ds
1000h
1000h 1000h
1123h 1000h
1123h 6622h 1000h
1123h 6622h 2211h 1000h
1123h 8833h 2211h 1000h
1123h 8833h 8833h 1000h
问题 3.4


mov ax,1000h ; ax = 1000h
mov ds,ax ; ds = 1000h
mov ax,11316 ; ax = 2c34h
mov [0],ax ; 1000:0000 = 2c34h
mov bx,[0] ; bx = 2c34h
sub bx,[2] ; bx = 1b12h
mov [2],bx ; 1000:0002 = 1b12h
3.4 mov、add、sub 指令

推测:
mov 段寄存器,寄存器
mov 寄存器,段寄存器 ;寄存器中得到的是段寄存器中的值
;;;;;;;;;;;;;;;;;;;;;
mov 内存单元,寄存器
mov 内存单元,段寄存器
mov 段寄存器,内存单元
总结下mov能进行的操作:
数据,寄存器,内存单元,段寄存器:
寄存器,数据
寄存器,寄存器
寄存器,内存单元
寄存器,段寄存器
内存单元,寄存器
内存单元,段寄存器
段寄存器,寄存器
段寄存器,内存单元
add 和 sub 同 mov 一样都有两个操作对象。
可以进行操作的是 :
数据,寄存器,内存单元。
add 和 sub 两者能进行的操作是相同的:
寄存器,数据
寄存器,寄存器
寄存器,内存单元
内存单元,寄存器
段寄存器不可以出现在算术指令中
3.5 数据段
根据需要,将一组内存单元定义为一个段。将一组长度为N(N<= 64KB)地址连续,起始地址为16倍数的内存单元当作专门存储数据的内存空间。
问题 3.5

mov bx, 1000h
mov ds,bx
mov ax,[0]
add ax,[2]
add ax,[4]
3.1-3.5 小结


检测点 3.1

mov ax,1
mov ds,ax ;ds = 0001h ; 后续都是 0001:XXXX
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


mov ax,6622h
jmp 0ff0:0100
mov ax,2000h
mov ds,ax
mov ax,[0008]
mov ax,[0002]
3.6 栈
LIFO (last in first out) 后进先出。
3.7 CPU提供的栈机制
两个最基本操作:push,pop
8086CPU的入栈和出栈都是以字为单位。
8086CPU中有两个寄存器SS和寄存器SP。
任意时刻: SS:SP指向栈顶的元素。
push ax
- SP = SP-2,SS:SP指向当前栈顶前面的单元,以当前前面的单元为新的栈顶
- 将ax中的内容送到SS:SP指向的内存单元出。此时SS:SP指向新的栈顶。
pop ax 操作相反
- 将SS:SP指向的数据pop到ax中。
- SP = SP+2
问题 3.6

;因为 栈操作的push操作是从大向小压栈。所以压入第一个数据时要 SP-2,也就是1000:000E。所以,SP = 000E+2 = 0010,所以SP应当为 0010h。
3.8 栈顶超界的问题
8086CPU不能保证对栈的操作不会越界,所以全凭写程序的人自己操心。
3.9 push 、pop 指令
两者可以进行的操作:
- push/pop 寄存器/段寄存器/内存单元
问题 3.7

mov ax,1000h
mov ss,ax
mov sp,0001h ;SS:SP已经组装完毕
push ax ;地址1000Fh
push bx ;地址1000Dh
push ds ;地址1000Bh
问题 3.8


;(1)
mov ax, 1000h
mov ss, ax
mov sp, 0001h
;栈已经组装好
;(2)
mov ax,001Ah
mov bx,001Bh
;(3)
push ax
push bx
;(4)
mov ax,0
mov bx,0
;(5)
pop bx
pop ax
问题 3.9

;(1)
mov ax,1000h
mov ss,ax
mov sp,0001h
;(2)
mov ax,001Ah
mov bx,001Bh
;(3)
push ax
push bx
pop ax
pop bx
问题 3.10

;用栈
mov ax,1000h
mov bx,ss
mov cx,sp
mov ss,ax
mov sp,0002h
mov ax,2266h
push ax
mov ss,bx
mov cx,cx
3.10 栈段
问题3.11

;因为10000h-1FFFFh这段矿建当作栈段,所以栈顶从最大+2开始 (因为push时,SP要先减2,得到1FFFFh 所以减去之前为加2),也就是SP=1FFFFh+2=20001h
所以此时的SP=20001h
问题 3.12

因为在压栈的时候是 SP-2 而 SP的范围是从 0000h~FFFFh,也就是说是2^16 Byte 也就是64KB。
检测点 3.2

mov ax,2000h
mov ss,ax
mov sp,0011h

mov ax,1000h
mov ss,ax
mov sp,0000h
实验 2 用机器指令和汇编指令编程
注意这里的SS和SP一起变化的,尽管是单步执行的情况下也是一同改变的。
目前只知道:Debug的T命令在执行修改寄存器SS的指令时,下一条指令也紧接着被执行。
2. 实验任务

ax = c0ea
ax = c0fc
bx = 30f0
bx = 6021
sp = 00FE ;2200:00FE C0FC
sp = 00FC ;2200:00FC 6021
sp = 00FE ;ax = 6021
sp = 0100 ;bx = C0FC
sp = 00FE 2200:00FE 30F0
sp = 00FC 2200:00FC 2F31
本文详细解析了8086 CPU中字的内存存储方式,段寄存器DS与偏移地址的使用,以及字的传送、数据段的概念。涉及mov指令的操作范围、栈的原理与操作,以及栈顶地址计算和堆栈溢出注意事项。适合理解8086汇编的基础教程。
第三章 寄存器(内存访问) 笔记&spm=1001.2101.3001.5002&articleId=125619045&d=1&t=3&u=5826970c728d4027bf7b94993cef38b7)
982

被折叠的 条评论
为什么被折叠?



