汇编语言中的ASSUME是什么意思?

6

在IT技术领域,人们经常说到绑定/关联寄存器和段的概念,但我想知道具体是什么被绑定了。


2
在NASM中,它意味着语法错误 "error: parser: instruction expected"。 - Ped7g
此回答解释了如何使用TASM或MASM来定义并调用一个过程。虽然这并不是您的问题的完全重复,但如果您阅读此特定答案和原始问题,它应该能够粗略地解释它。要获得更准确的定义,您可以已经阅读TASM或MASM文档。 - Ped7g
1
我编辑了你的问题,使其更易读(在我看来)。请随意使用左下角的“编辑”按钮回滚更改。 - Margaret Bloom
1个回答

12
ASSUME 指令告诉汇编器使用哪个段寄存器来访问一个段。
这种“绑定”对自动化一些常见模式很有用:
1. 它告诉汇编器使用哪个段寄存器来访问一个变量。 如果在内存访问期间未显式指定段寄存器,则汇编器使用 ASSUME 的值自动向指令添加一个“段覆盖前缀”。 如果尚未将某个段 ASSUME 为任何段寄存器所指向的段,则如果您尝试在其中加载/存储变量,汇编器会失败并显示错误。
2. 它告诉汇编器针对哪个段计算偏移量。 如果在内存访问期间指定了段寄存器,则汇编器将使用为该段寄存器 ASSUME 的段来计算内存访问的偏移量。 请注意,尽管 CPU 在每次内存访问时隐式使用 DS,但需要使用 DS: 明确表示将其段用作偏移基数的意图。
3. 由 CS ASSUME 的段是代码标签所属的段。 除非符号位于由 CS ASSUME 的段中,否则无法跳转/调用它。
考虑下面的程序,它不打算运行,只想进行反汇编。
.MODEL SMALL
.286

;Segment are laid out sequentially, starting from X and aligned on 16 bytes.
;
;_DATI     X
;_DATI2    X + 10h
;_DATI3    X + 20h
;
;All the variables testX are the first variables in a segment so their
;addresses are the same of their segments

_DATI SEGMENT PARA PUBLIC 'DATA' USE16

   test1 dw 0

_DATI ENDS

_DATI2 SEGMENT PARA PUBLIC 'DATA' USE16

   test2 dw 0

_DATI2 ENDS

_DATI3 SEGMENT PARA PUBLIC 'DATA' USE16

   test3 dw 0

_DATI3 ENDS

_CODE SEGMENT PARA PUBLIC 'CODE' USE16

 ;Use CS to access labels defined inside _CODE and use _CODE to compute those offsets
 ;Use DS to access names defined inside _DATI and use _DATI to compute offsets whenever DS is explicitly used as a segment register
 ;... and so on

 ASSUME CS:_CODE, DS:_DATI, ES:_DATI2

 ;NOTE: _DATI3 NOT ASSUMED!

__START__:

  ;No explicit segment override, find the segment of test1 (_DATI) and use
  ;the assumed register (DS).
  ;Assembled into mov ax, WORD PTR [0000] (A1 00 00)     
  mov ax, WORD PTR [test1]  

  ;No explicit segment override, find the segment of test2 (_DATI2) and use
  ;the assumed register (ES).
  ;Assembled into mov bx, WORD PTR es:[0000] (26 8B 1E 00 00)
  mov bx, WORD PTR [test2]

  ;Explicit segment override, use the segment assumed for ES (_DATI2) to
  ;calculate the offset (0000h).
  ;Assembled as the previous mov cx, WORD PTR es:[0000] (26 8B 0E 00 00)
  mov cx, WORD PTR es:[test2]

  ;Explicit segment override, use the segment assumed for DS (_DATI) to
  ;calculate the offset (0010h).
  ;Assembled as the previous mov dx, WORD PTR es:[0010] (8B 16 10 00)
  mov dx, WORD PTR ds:[test2]

  ;OFFSET of X is always relative to the segment X is declared in. 
  ;This is true for MASM mode only, IDEAL mode use the group

  ;Both use an offset of 0, as both test1 and test2 are the first variables
  ;of their segments
  mov ax, OFFSET test1              ;mov ax, 0000  (B8 00 00)
  mov bx, OFFSET test2              ;mov bx, 0000  (BB 00 00)

  ;No explicit segment override, find the segment of test3 (_DATI3) and
  ;use the assumed register (none)
  ;Can't assemly: error -> Can't address with currently ASSUMEd segment registers
  mov ax, WORD PTR [test3]  

  ;Explicit segment override, calculate offset of test3 with respect of the
  ;segment assumed for DS (_DATI)
  ;Offset is 20h
  mov bx, WORD PTR ds:[test3]       ;mov bx, WORD PTR [0020] (8B 1E 20 00)

  ;OFFSET operator don't use assumed register
  mov cx, OFFSET test3
_CODE ENDS

END __START__

如果您没有ASSUME CS,汇编器会报错:

当前段无法到达 CS

因为您在一个没有被任何地方ASSUME的代码段中定义了一个标签__START__

我在第二点遇到了困难。如果我理解正确的话,这意味着如果给定mov dx, WORD PTR ds:[test2],汇编器将计算相对于_DATI段开头的test2的偏移量,得到0010h。然而,在我的反汇编中,我发现test2被计算为位于偏移量0000h处(即相对于_DATI2而不是_DATI)。我使用TASM 4.1和MASM 6.14汇编了上面的清单(不包括错误的行),在两种情况下都看到了相同的结果。我是否误解了这一点,或者您知道什么可以解释这种差异? - ntwk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接