10.16汇编

Posted on Oct 16, 2020
some nights

今天的进度非常慢,到11点多才刚刚结束了第三章,总体不是很满意。

SS,SP和栈的故事

SS是另一种段寄存器(至今为止碰到的第3种,之前的是CS(代码段寄存器)和DS(为[address]服务)),主要是为内存栈提供段地址,而SP则提供了偏移地址。内存栈以字为单位存储,同样是高地址存字的高位,因此每次SP改变的值都是2。

需要注意的有两个点:

1、SP是从地址从高位到地位“递增”的,即元素出栈则SP增大(到低位),元素入栈SP减小(到高位),因此,栈底是内存地址最大的部分。

2、在栈为空的时候,SP指向栈内存空间最高位的上一位(地址位+1),这是因为任何时刻SS:SP都是指向栈顶元素的。

我对内存栈的理解

内存栈并不是预设的,而是人为模拟的,所谓栈顶和栈底都应该是人为规定的,对于CPU而言并无法判断是否越界,所以必须要对栈空间分配做好精确的估计,否则若出现溢出,不仅可能在运行时出现BUG,更可能增加受到溢出攻击的风险。

栈操作

压栈:push ax 退栈:pop bx 。退栈过程中,会把退出的值赋值给bx。寄存器不是一定要为通用寄存器,段寄存器同时也可以,内存空间也是可以的(即[..])。

由于栈操作时,SS并不会改变,所以可以认为栈最大的空间只有FFFFH,即只能存8888H个字。

栈段和代码段数据段什么的类似,方便管理罢了,没什么特别的。

段的综述

段只是用户对内存的一种抽象,CPU并不会真的把内存分段,实现分段效果的根本方法是人为指定CS,DS,SS的值,并通过IP,[..],SP来进行访问。段可以复用,可以即是代码段,又是数据段,又是栈,CPU到底把段看作什么,都是靠几个寄存器实现的。CPU会把内存“当作”段来执行,原因也只是段寄存器的存在。这一点非常重要,一定要重视。 灵活运用内存类型,可以有效的优化代码,比如检测点3.2的第一题。

实验中提到的一个问题,在debug中单步执行对SS修改过之后,下一条指令会直接执行,原因是中断机制,具体原因王爽则按下不表,暂且记住吧。

而在实验中提出的思考题也是同样的原因,由于单步中断,一些数据被存到了栈中,导致数据的改变。


源程序从写出到执行的过程

再强化一遍,汇编源文件通过编译,产生目标文件,通过连接器,产生可执行文件。

可执行文件包括两个部分:程序(指令码)、数据(立即数)与相关描述信息(占有的内存等)

汇编指令和伪指令

伪指令就是所有没有对应机器码的指令,只是为了让编译器执行。

很重要的是segment..ends伪指令,作用是定义段,有意义的汇编代码,必须包含至少一个段用以存放代码。

codesg segment
    ..
    ..
codesg ends
;这样就定义了一个名为codesg的段

end :程序结束符,不能省略,加在尾处,没啥好说的。

assume:将特定的段和特定寄存器关联,比如代码段就和CS关联,那么就是assume cs:codesg