资料来源:汇编语言第二版-王爽
1.mov,add,sub指令
mov指令有以下几种形式:
mov 寄存器,数据 比如:mov ax, 8
mov 寄存器,寄存器 比如:mov ax, bx
mov 寄存器,内存单元 比如:mov ax, ds:[0]
mov 内存单元,寄存器 比如:mov ds:[0], ax
mov 内存单元,段寄存器 比如:mov ds:[0], cs
mov 段寄存器,内存单元 比如:mov cs, ds:[0]
mov 段寄存器,寄存器 比如:mov ds, ax
mov 寄存器,段寄存器 比如:mov ax, cs
add和sub指令同mov指令一样,都有两个操作对象。它们也可以有以下几种形式:
add 寄存器,数据 比如:add ax, 8
add 寄存器,寄存器 比如:add ax, bx
add 寄存器,内存单元 比如:add ax, ds:[0]
add 内存单元,寄存器 比如:add ds:[0], ax
sub 寄存器,数据 比如:sub ax, 8
sub 寄存器,寄存器 比如:sub ax, bx
sub 寄存器,内存单元 比如:sub ax, ds:[0]
sub 内存单元,寄存器 比如:sub ds:[0], ax
2.栈
8086CPU中,ss是栈段寄存器,sp是栈顶指针寄存器,栈顶的段地址存放在ss中,偏移地址存放在sp中。
任意时刻,ss:sp指向栈顶元素。
栈有两个基本操作:入栈(push)和出栈(pop)。
puss指令和pop指令执行时,CPU从ss和sp中得到栈顶的位置。
入栈就是将一个新的元素放到栈顶,出栈就是从栈顶取出一个元素。
栈的操作规则为:LIFO(Last In First Out,后进先出)
push ax //表示将通用寄存器ax中的数据送入栈中
pop ax //表示从栈顶取出数据送入通用寄存器ax中
push ax的执行,由以下两步完成:
(1)sp=sp-2,ss:sp指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶;
(2)将通用寄存器ax中的内容送入ss:sp指向的内存单元处,ss:sp此时指向新的栈顶。
pop ax的执行过程和push ax刚好相反,由以下两步完成:
(1)将ss:sp指向的内容单元处的数据送入通用寄存器ax中;
(2)sp=sp+2,ss:sp指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。
3.push和pop指令的格式可以是如下形式:
push 寄存器 比如:push ax 入栈,将通用寄存器ax中的数据放入栈中
pop 寄存器 比如:pop ax 出栈,用通用寄存器ax接收从栈中取出的数据
push 段寄存器 比如:push ds 入栈,将段寄存器ds中的数据放入栈中
pop 段寄存器 比如:pop ds 出栈,用段寄存器ds接收从栈中取出的数据
push 内存单元 比如:push ds:[0] 入栈,将内存单元ds:[0]中的数据放入栈中
pop 内存单元 比如:pop ds:[0] 出栈,用内存单元ds:[0]接收从栈中取出的数据
4.push、pop实质上是一种内存传送指令,注意它们的灵活应用。
5.栈段的大小为16的倍数
一个栈空间中有N个字节,则这个栈段的空间大小为:16 * (N / 16 + 1)
6.栈顶超界问题
8086CPU只记录栈顶,栈空间的大小需要我们自己管理。
我们在编程的时候要自己操心栈顶超界的问题,要根据可能用到的最大栈空间,来安排栈的大小,防止入栈的数据太多而导致的超界;执行出栈操作的时候也要注意,以防栈空的时候继续出栈而导致的超界。
ss指示栈段段地址,sp指示当前栈顶指针,CPU只会根据栈的操作指令进行数据的读写,所以越界访问有可能会出现未知错误。
有错误请指正,谢谢。