@@ -11,7 +11,7 @@ cpu中用16位寄存器来存储一个字. 高8位存放高位字节, 低8位存
11
11
12
12
比如要读取10000H中的内容
13
13
14
- ``` s
14
+ ``` asm
15
15
mov bx,1000H
16
16
mov ds,bx
17
17
mov al,[0]
@@ -47,7 +47,7 @@ mov,add,sub指令形式:
47
47
48
48
如将` 123B0H~123B9H ` 的内存单元定义为数据段(起始地址` 123BH ` , 长度为` 10 ` 个字节),现在需要累加该数据段前3个单元中的数据
49
49
50
- ``` s
50
+ ``` asm
51
51
52
52
mov ax,123B
53
53
mov ds,ax
@@ -64,7 +64,7 @@ add al,[2]
64
64
65
65
有如下指令
66
66
67
- ``` s
67
+ ``` asm
68
68
mov ax,0123H
69
69
push ax
70
70
mov bx,2266H
@@ -98,4 +98,83 @@ pop cx
98
98
1 . 将` SS:SP ` 指向内存单元处的数据送入` ax ` 中
99
99
2 . ` SP=SP+2 ` ,` SS:SP ` 指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶
100
100
101
- ![ ] ( ../snapshots/3.12.png )
101
+ ![ ] ( ../snapshots/3.12.png )
102
+
103
+ 出栈后, ` SS:SP ` 指向新的栈顶` 1000EH ` , 之前的栈顶` 1000CH ` 处的数据` 2266H ` 依然存在, 只是不再栈中. 当再次执行` push ` 等入栈指令后, ` SS:SP ` 移至` 1000CH ` , 并在里面写入新的数据将其覆盖
104
+
105
+ ## 栈空间超界问题
106
+
107
+
108
+ 8086CPU不保证对栈的操作不会超界. 8086CPU只知道栈顶在何处(由SS: SP 指示),而不知道我们安排的栈空间有多大.
109
+
110
+ ## push,pop指令
111
+ push, pop等栈操作指令, 修改的只是` SP ` . 栈顶的变化范围最大为` 0~FFFFH `
112
+
113
+ 8086CPU的栈操作机制:
114
+
115
+ 1 . 提供` SS ` ,` SP ` 指示栈顶
116
+ 2 . 改变` SP ` 后写内存的入栈指令
117
+ 3 . 读内存后改变` SP ` 的出栈指令
118
+
119
+ 形式:
120
+ | 指令 | 解释 |
121
+ | ---- | ---- |
122
+ | push 寄存器 | 将一个寄存器中的数据入栈 |
123
+ | pop 寄存器 | 出栈, 用一个寄存器接收出栈的数据 |
124
+ | push 段寄存器 | 将一个` 段寄存器 ` 中的数据入栈 |
125
+ | pop 段寄存器 | 出栈, 用一个` 段寄存器 ` 接收出栈的数据 |
126
+ | push 内存单元 | 将一个内存` 字单元 ` 处的字入栈(注: 栈操作都是以字为单位) |
127
+ | pop 内存单元 | 出栈, 用一个` 内存单元 ` 接收出栈的数据 |
128
+
129
+ ``` asm
130
+ mov ax,1000H
131
+ mov ds,ax ;内存单元的段地址要放在ds中
132
+ push [0] ;将1000:0处的字压入栈中
133
+ pop [2] ;出栈, 出栈的数据送入1000:2处
134
+ ```
135
+
136
+ 编程:
137
+ 1 . 将` 10000H~1000FH ` 这段空间当做栈,初始状态栈是空的
138
+ 2 . 设置` AX=001AH, BX=001BH `
139
+ 3 . 将AX,BX中的数据入栈
140
+ 4 . 然后将AX,BX清零
141
+ 5 . 从栈中回复AX,BX原来的内容
142
+
143
+ ``` asm
144
+ mov ax,1000H
145
+ mov ss,ax
146
+ mov sp,0010H ;初始化栈顶
147
+ mov ax,001AH
148
+ mov bx,001BH
149
+
150
+ push ax
151
+ push bx ;ax,bx入栈
152
+
153
+ sub ax,ax ;将ax清零, 也可以使用mov ax,0
154
+ ;sub ax,ax的机器码为2个字节
155
+ ;mov ax,0的机器码为3个字节
156
+ sub bx,bx
157
+
158
+ pop bx ;从栈中回复ax,bx原来的数据,当前栈顶的内容是bx
159
+ pop ax ;ax中原来的内容001AH在栈顶的下面, 所以要先pop bx,再pop ax
160
+
161
+ ```
162
+
163
+ ![ ] ( ../snapshots/3.15.png )
164
+
165
+
166
+ ## 栈段
167
+
168
+ #### 段
169
+ 我们可以将一段内存定义为一个段, 用一个段地址指示段, 用偏移地址访问段内的单元.这完全是我们自己的安排
170
+ 1 . 数据段
171
+ - 用一个段存放数据(ds寄存器)
172
+ - 用` mov,add,sub ` 等访问内存单元的指令时,cpu就将数据段中的内容当做数据来访问
173
+ 2 . 代码段:
174
+ - 用一个段存放代码(cs寄存器)
175
+ - 将断种第一条指令的偏移地址放在ip寄存器中,cpu就将执行代码段中的指令
176
+ 3 . 栈段:
177
+ - 用一个段当做栈(ss寄存器)
178
+ - 将栈顶单元的偏移地址放到sp寄存器中,cpu在执行` push,pop ` 指令时将栈段当做栈空间来用
179
+
180
+ 一段内存,可以既是代码的存储空间,又是数据的存储空间,还可以是栈空间,也可以都不是. 关键在于cpu中寄存器的设置,即` cs,ip,ss,sp,ds ` 的指向
0 commit comments