关于汇编中ASSUME的讨论

【转】
2011年11月23日 星期三 20:33
转载自 dandanfeng166
最终编辑 undeadnightelf

对于汇编中ASSUME的作用及,一直都没有弄清楚,下面是百度汇编吧中对这一问题的讨论:

(篇幅过长,没时间细看的,请重点看24楼,72楼和补充知识。)

问题来源:百度汇编吧:ASSUME的作用?在实际应用中我糊涂了

ASSUME DS: DATA <---- 既然已经将DATA分配给DS
ASSUME ES: EXTR
...
...
MOV AX, DATA <---- 为什么还要把DATA的地址赋值给DS
MOV DS, AX 


MOV AX, EXTR
MOV ES, AX

对于问题的回答中,自己认为比较合理的部分,节选如下:

24楼,无名人士:

在数据段中定义的每一个变量标志符其实都代表了一个偏移量(也称为有效地址),这个偏移量与数据段段值相结合就指向某个内存地址。在程序中使用 ASSUME伪指令是用来指明一个默认的段地址。一旦你把某个数据段的段名指定给某个段寄存器(比如ASSUME DS,DATA1),这之后当你使用这个数据段(DATA1)内定义的变量,编译程序就自动把它与这个段寄存器(DS)里的段值(表示一个段地址)结合起来使用。

所以,assume并不分配内存,前面提到的确立对应关系其实就是为了以后能用上段里面的变量.要不以后用到段里面定义的变量时就不知道基地址是什么了

 29楼:

 我们汇编英文版这样说的:
 When the program loader leads an .exe program from disk into  memory for execution,it constructs a 256-byte(100h)psp(program segment prefix)on a paragraph boundary in available internal memory and stores the porgram immediately following the boundary. the loader then
 ..initializes the address of the code segment in cs
 ..initializes the address of the stacd segment in ss and
 ..initializes the address of the psp in ds and es (我的注释:把psp的值赋给ds和es)
看到最后一句了吗,这就是说 assume cs:data,ds:data,ss:data 这句其实已经分别给cs,ds和ss段寄存
器相应赋值了,但是随后加载器又把psp的地址赋给了ds和es寄存器,而我们要的ds地址不是psp,这是在
代码执行之前完成的,所以我们要在代码中显示地指明MOV AX,DATA MOV DS,AX ,而不用指明cs,ds及
ss的寄存器。

 

31楼,无名人士(不一定对,但有参考价值)

回复30及以上的:
 看来你们还是不很了解伪操作的意思,伪操作只是不产生实际的指令,就像c语言中的类型定义: int i=1; 它不产生实际的指令代码,但是它确实为我们做了一些事,那就是向系统申请了i这个int型空间,并在&i这个地址里放入值1,这样系统在执行这个程序之前,就会为程序分配这个数据空间i,并在里面放入初值1,做了这些准备之后,才开始执行真正的可执行指令。同样,assume这个伪操作一样,它实际为各个段寄存器装入初值了,不要被伪操作不产生实际的代码这句话误导了!

 

35楼:无名人士(程序验证)

我的masm不要assume也没什么区别(不知道其他的编译器怎样)用debug查看寄存器cs ds es ss都还是有初值(而且我没有用mov ax,data mov ds,ax语句)
这样没有任何显示的让ds指向那个段+没有assume语句后:ds是指向psp的 所以以后mov ax,[0] 用debug查看到ax=CD(psp开始部分两个字节就是CD
不过assume没有为段寄存器赋值那是对的,以下是验证程序
data segment
     db 4dh
data ends
stack segment
     db 4eh
stack ends
assume ds:stack    ;让ds与stack关联而不是与data
code segment
start:mov ax,[0]        ;没有让ds重新定向
      cmp ax,0CDH
    abc:je abc             ;如assume无赋值作用,则程序在此将进入死循环(事实上确实死循环)
      mov ax,4c00h
      int 21h
code ends
end start
///根据猜想,如果assume如果是赋值了的话 那么mov ax,[0]后ax应该是4eh
       但实际上是什么呢?
        ax仍然是0CDH,即ds的初始指向仍然是psp的起始位置,除非后来用显示语句
       mov ax,data
        mov ds,ax
      这样的语句显示的重新定位ds,ds才会指向数据段

 

60楼:(从百度知道搜的)

问:汇编语言中的psp空间干什么用的(能自己拿来用吗?)??
答:段前缀是操作系统在执行程序时为程序所建立的一个信息块,    里面包括了传递给待运行程序的命令行参数,    程序运行结束时返回DOS所需的地址等有用的信息.   
   COM格式比较特殊,数据段,代码段,堆栈段集中在一个段里,连PSP也集中在这个段里,    于是段的前100H就用来存放PSP了.
EXE文件在运行时DS/ES的初值设为PSP的段地址,可以直接用偏移0-100H访问PSP的内容。

 

72楼:

我觉得下面的说法更精华:
要用assume把段跟段寄存器对应起来的原因是原来的DOS找到的空闲内存的地址不是固定的,无法找到一个地址在任何时候都是空闲的。于是DOS需要可以重定位的程序,而当时的定位方式就是设置段寄存器的值使该程序能在可分配(空闲)的内存中可用。那就需要知道某个段被重定位时候需要修改哪个段寄存器的值才能正确执行。assume提供这种段和重定位代码时需要对应修改的寄存器的关系给编译器,编译器再这个信息写到二进制文件中去。比如DOS下的exe程序记录在文件头中。

 

**********补充知识**********************

汇编语言PSP知识

来自百度知道:http://zhidao.baidu.com/question/195901151.html?fr=qrl&cid=865&index=1&fr2=query

一般来说,PSP是256个字节,当程度生成了可执行文件以后,在执行的时候,先将程序调入内存,这个时候DS中存入程序在内存中的段地址,紧接着是程序的一些说明,比如说程序占用多大空间等等,这就是PSP,一般PSP占256个字节,然后才是真正的程序地址,将CS指向这里,IP设为0000,为什么一般CS要比DS大10H,就是因为这个原因,简单说:DS存放的是程序段地址,由于PSP的存在,真正要执行的地址是DS再加上256个字节,真正的地址是DS*16+256化简一下:DS*16+0+16*16=16*(DS+16)真正的地址又可以写成:cs*16+0 所以CS相当于DS+16,化成十六制是DS+10


  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值