. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->汇编语言学习交流区
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  assume的作用探讨  [待解决] 回复[ 16次 ]   点击[ 1757次 ]  
cnhnyu
[帖 主]   [ 发表时间:2007-11-23 12:29 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2007-10-22 14:47
关于assume的作用,许多人都简单的解释说,这是告诉编译器哪一个段和哪一个段寄存器相关联。举个简单例子来说:
assume cs:code, ds:data
这是告诉编译器cs和code关联,ds和data关联,后来又看到这样的代码
mov ax, data
mov ds, ax
让许多人一头雾水,既然ds和data关联了,怎么又要把data的值送到ds,这到底是怎么回事?
这里,先不做过多的说明,我们先看看下面这个例子:

下面的程序,把data段中的字符串拷贝到dseg段中,并且调用dos的21h中断的9号功能来显示
dseg段中的字符串:

;segtest.asm
data segment
        msg        db        'Hello, how are you ?', 0dh, 0ah, 24h
data ends

dseg segment
        hello        db        32  dup(0)
                db      0dh, 0ah, 24h
dseg ends

code segment
        assume cs:code, ds:dseg, es:data
start:
        mov ax, dseg
        mov ds, ax    ; 把dseg段的段地址送入ds

        mov ax, data
        mov es, ax   ; 把data段的段地址送入es

        mov si, offset msg      ; 把源字符串的偏移送入si
        mov di, offset hello    ; 把目标字符串的偏移送入di
cploop:
        mov al, msg[si]; (1)这里是一个寄存器相对寻址,那么这个物理地址是怎么形成的呢?
        cmp al, 24h
        jz ok
        mov hello[di], al; (2)这里又是一个寄存器相对寻址,这个物理地址又是怎么形成的?
        inc si
        inc di
        jmp short cploop

ok:
        mov dx, offset hello
        mov ah, 9h
        int 21h

        mov ax, 4c00h
        int 21h
code ends
        end start

对于(1)和(2)中两个地址的形成我们来分析一下:
这两个都是寄存器相对寻址,即有效地址都是一个寄存器加上一个16位的偏移量
对于(1) EA = (si) + msg的偏移地址
     物理地址就是: (段寄存器)×16+EA
     段寄存器有四个cs, ds, es, ss, 那么编译器怎么知道用哪一个呢? 这里就显示出了assume的作用,是assume告诉了编译器,data段中的标号的段地址要从es中取得,即这一句:
es:data  告诉了编译器在data segment和data ends之间的所有的标号都要使用es作为段寄存器来寻址,于是当编译器看到这个msg标号的时候,它就知道了这里物理地址的形成是用(es)×16+EA
同理,对于(2),当编译器看到hello这个标号的时候,它就知道要取ds中的值作为段地址。如果没有
assume说明哪一个段和哪一个寄存器关联,那么,编译器就无法确定到底用哪一个段寄存器来计算物理地址。

从这里,我们也可以看出,assume的作用仅仅是告诉编译器,我碰到一个标号,要计算它的物理地址的时候,从哪一个段寄存器里面取出段值,至于这个段寄存器的值对不对,那它就不管了,这是程序员的事情,反正它只管根据assume里面的设定来用段寄存器,所以,对于程序员来说,不仅要用assume告诉编译器计算物理地址的时候要从哪一个段寄存器取值,而且要在指令中明确的把对应段的段值送到设定好的段寄存器中。
用伪指令assume告诉编译器,data段中的标号的段地址要从es中取值,而指令
mov ax, data
mov es, ax
则把data段的段地址送入es中,这样编译器计算msg标号的物理地址的时候,才能得到正确的段地址。

当然,如果你不用assume指明哪一个段和哪一个寄存器相关联,比如我把assume cs:code, ds:dseg, es:data改为
assume cs:code这也可以,即我不把ds和dseg关联,也不把es和data关联,但是你必须在指令中明确的告诉编译器使用哪一个段寄存器
指令mov al, msg[si]必须改为 mov al, es:msg[si], 而指令mov hello[di], al也必须改为mov ds:hello[di], al,这样编译器才能知道使用哪一个段寄存器计算物理地址。如果编译器无法确定标号的段地址,那么程序编译就不会通过。

这是我的个人简短的分析,不知道正确与否,欢迎大家批评指正。【http://www.anijh.cn】
cxn
[第1楼]   [ 回复时间:2007-11-23 14:41 ]   [引用]   [回复]   [ top ] 
荣誉值:179
信誉值:6
注册日期:2007-07-09 19:18
不错,是这么回事.
fishboy
[第2楼]   [ 回复时间:2007-11-23 15:59 ]   [引用]   [回复]   [ top ] 
荣誉值:283
信誉值:0
注册日期:2007-06-26 11:42
恩。说的很明白!
mouse
[第3楼]   [ 回复时间:2007-11-27 19:45 ]   [引用]   [回复]   [ top ] 
荣誉值:472
信誉值:12
注册日期:2007-10-16 15:34
太利害了,我都没有想过....
damingyu
[第4楼]   [ 回复时间:2007-12-05 22:34 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2007-11-04 21:00
这个是两次扫描时第一次用的
taotling
[第5楼]   [ 回复时间:2008-03-10 14:48 ]   [引用]   [回复]   [ top ] 
荣誉值:53
信誉值:0
注册日期:2008-02-09 02:55
学习了!
wdm
[第6楼]   [ 回复时间:2008-03-11 14:06 ]   [引用]   [回复]   [ top ] 
荣誉值:342
信誉值:0
注册日期:2007-12-06 10:21
说的很到位啊。
abc58139966
[第7楼]   [ 回复时间:2008-03-20 17:09 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2007-10-24 17:00
assume esi:image_data_bit(后面是一个结构数据)那这你又怎么解释呢这位兄弟.
abc58139966
[第8楼]   [ 回复时间:2008-03-20 17:12 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2007-10-24 17:00
写错了ASSUME ESI:PTR IMAGE_DATA_BIT
custa
[第9楼]   [ 回复时间:2008-12-16 13:41 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2008-10-22 19:04
mov si, offset msg      ; 把源字符串的偏移送入si 
  mov di, offset hello    ; 把目标字符串的偏移送入di 
这两条指令好像不对。
得改为
  mov si, 0 
  mov di, 0
custa
[第10楼]   [ 回复时间:2008-12-16 13:47 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2008-10-22 19:04
这道题是没出错,
不过如果在msg,hello 前再定义其它变量的话就错了。
abob
[第11楼]   [ 回复时间:2009-01-04 14:47 ]   [引用]   [回复]   [ top ] 
荣誉值:169
信誉值:0
注册日期:2008-08-19 16:07
不错 ^_^
itx
[第12楼]   [ 回复时间:2010-05-02 00:04 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2009-11-25 23:56
举那个例子太长了点吧。 不过意思还是对的。
anuya
[第13楼]   [ 回复时间:2010-09-17 15:49 ]   [引用]   [回复]   [ top ] 
荣誉值:2
信誉值:0
注册日期:2010-09-13 18:17
学习了!不错
tydong88
[第14楼]   [ 回复时间:2011-11-23 13:02 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2011-11-23 12:58
楼主说的很好,不过有个问题我想请教一下楼主,如下:
 设有语句ASSUME CS:DESG DS:DESG,现已知标号X属于DESG段,那么X的段值是从CS中取还是从DS中取?
chinatree
[第15楼]   [ 回复时间:2011-11-23 14:19 ]   [引用]   [回复]   [ top ] 
荣誉值:118
信誉值:0
注册日期:2011-07-07 22:59
应该是都可以吧。
wxshehe
[第16楼]   [ 回复时间:2012-12-16 14:45 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2012-11-28 19:08
那这样呢
mov ax,desg
mov ds,ax
 物理地址就是: (段寄存器)×16+EA 
     段寄存器有四个cs, ds, es, ss, 那么编译器怎么知道用哪一个呢? 这里就显示出了assume的作用,是assume告诉了编译器,data段中的标号的段地址要从es中取得,即这一句: 
es:data  告诉了编译器在data segment和data ends之间的所有的标号都要使用es作为段寄存器来寻址,于是当编译器看到这个msg标号的时候,它就知道了这里物理地址的形成是用(es)×16+EA
需要登录后才能回帖 -->> 请单击此处登录
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved