栈段
和代码段、数据段一样,栈也被定义为一个内存段,叫做栈段,由段寄存器ss指向
-
定义栈段
- 初始化段寄存器ss--->指向栈段的首地址
- 初始化栈指针sp--->指向栈顶字节(以字为单位移动),初始化时指向栈段最后一个字节的下一字节,其实就等于分配给栈段的字节数
-
栈操作
- push:压栈,sp的值减2
- pop:出栈,sp的值加2
-
作用
- 临时存储数据
- 保护数据,比方说先将寄存器ax的值压入栈中,然后有个函数更改了ax的值,函数结束后再将栈中的值弹出,由ax接受,这样就保护了ax的内容
-
注意点
- push/pop指令的操作数是16位寄存器或16为内存单元,一个字的大小
- 栈本质上只是普通的内存区域,用push/pop指令来访问
- 保持栈的平衡,出栈与入栈要成对(即push和pop的数目一样)
- 在编写程序前,充分估计所需要的栈空间,放置破坏有用的数据
- 将栈定义到一个单独的段中,可以是错误仅局限于栈,sp的内容只会在栈段的地址范围来回滚动,不影响其他内存段
-
bochs调试显示栈的内容
print-stack
命令用于显示栈顶以下的16个字的内容,第一个地址最低的就是栈顶
栈是由高地址向低地址生长的,即栈顶是低地址
寻址方式
- 寄存器寻址:指令的操作数位于寄存器中
- 立即寻址:指令的操作数是一个立即数
- 内存寻址:实际上就是寻找偏移地址,这称为有效地址,段地址由4个段寄存器提供
- 直接寻址:操作数是一个偏移地址,而且给出了该偏移地址的具体数值,无需计算(段超越前缀和标号,不涉及计算时也是直接寻址)
- 基址寻址:在指令的地址部分使用bx或bp寄存器来提供偏移地址
当我们使用栈时,我们只能访问栈顶元素,若是想不改变sp去访问元素,可以先将sp的值赋给bp,然后在去添加元素等等,这时候就可以通过bp访问栈顶以下的元素而不改变sp了 - 变址寻址:类似基址寻址,只不过使用的是变址寄存器(si和di)
- 基址变址寻址:同时使用bx/bp和si/di这两类寄存器