Assume指令解析
刚学习80X86汇编的时候,有一条称为段分配伪指令Assume,我刚开始看这个的时候,就一直没看懂什么意思,老师也仅仅就说了一下,必须得这样,至于更深层次的讨论就没有,所以关于assume指令一直是懵懵懂懂的。这些天才回过头来看的话,貌似有一点感悟!很久没写点文章了,就写下自己对于assume的理解吧。
很多书上说的是assume指令使段寄存器与某个段关联起来,但是assume指令是伪指令,还必须通过指令来赋值给段寄存器。这话第一次看的时候,确实很迷茫。在这里我试着从另外的一个角度去理解assume指令。
还是先来个例子(为了突出重点,例子都是很简单,甚至仅为测试而写,没有实际意义)
DATA SEGMENT ;数据段
MESS DB "HELLO",0DH,0AH,'$'
DATA ENDS
;
CODE SEGMENT ;代码段
ASSUME CS:CODE,DS:DATA
START: MOV AX,DATA
MOV DS,AX
offset指令是什么意思 MOV DX,OFFSET MESS
MOV AH,9 ;显示信息HELLO
INT 21H
MOV AH,4CH
INT 21H ;返回DOS
CODE ENDS
END START
在这个程序中,红指令对应的是取得MESS的偏移地址,当我们对于MESS进行访问时候,汇编程序识别呢?我看可以这么理解哈,首先看到MESS的时候,汇编程序察觉这个是在DATA段中定义的变量,但是要访问它的时候,必须知道它的确切地址才行,所以在DATA段中,必须知道DATA的段地址,这个时候程序开始的前两条语句就已经给DS赋予了值,但是我们如何得知DS和DATA的关系呢?这个时候就是assume的作用了,它就是告诉汇编程序,用指定的段寄存器寻址相应的逻辑段,建立段寄存器与段的默认关系。所以程序的开始用的是两个assume指令使代码段与数据段和指定的寄存器关联起来,程序的段地址知道了,偏移地址就是汇编程序地址计数器在进行汇编的时候自动算出来的,这个不用我们担心!
另外在dos装入EXE程序的时候,DS和ES被初始化为PSP(程序段前缀)的段地址,而不是用本身的数据段和附加数据段,所以源程序中必须重新初始化DS和ES。CS:IP指向源程序的代码段,cs必须被关联到指定的段,否则程序不能运行(代码段必须用ASSUME CS:CODE指明,否则编译器不知道代码从何处开始执行,编译不通过)。SS:SP指向程序的堆栈段,如果程序未设堆栈,则SS为PSP的段地址加上256个字节,SP为00h。
上面说的可能还是不太清楚,写2个例子在下面看哈或许更明白些吧
DATA SEGMENT ;数据段
MESS DB "HELLO",0DH,0AH,'$'
DATA ENDS ;
CODE SEGMENT ;代码段
ASSUME CS:CODE,ES:DATA ;用ES关联,一样的效果
; ASSUME CS:CODE,DS:DATA
START: MOV AX,DATA
MOV ES,AX
mov al,mess + 1
or al,20h ;大写变小写
mov mess+1,al
MOV AX,ES
MOV DS,AX
MOV DX,OFFSET MESS
MOV AH,9 ;显示信息HELLO
INT 21H
MOV AH,4CH
INT 21H ;返回DOS
CODE ENDS
END START
结果输出的是HeLLO
我们可以把红代码换成ASSUME CS:CODE,DS:DATA,输出结果是HELLO,即没有变化。我们可以看下反汇编的代码就一切明白了。
这个是没有改动的,可以看到访问变量mess的时候,自动加上了es段寄存器,这个就是assume的作用。如果改成ASSUME CS:CODE,DS:DATA,那么访问mess的话,则自动关联到ds寄存器,但是我们的程序中ds的值没有赋值,即ds的值还是原来程序段前缀的段地址,所以我们写的大小写转换不是在操作我们的数据,而是PSP中的某个数据,看下图:
相信说到这了,大家应该有一点稍微清晰的认识吧!
(原文参看了部分书籍的介绍)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论