5

Everywhere it is explained as a thing which binds/associates registers with segments, but I want to understand what is bound exactly.

Margaret Bloom
  • 41,768
  • 5
  • 78
  • 124
  • 2
    In NASM it means syntax error "error: parser: instruction expected". – Ped7g Dec 05 '16 at 19:13
  • http://stackoverflow.com/a/39187939/4271923 (it's not exactly duplicate of your question, but if you will read this particular answer vs original question, it should roughly explain it ... for more accurate definition you could have already read the TASM or MASM documentation). – Ped7g Dec 05 '16 at 19:27
  • 1
    I edited your question to make it more readable (in my opinion). Fell free to use the "edit" button on the lower left corner to rollback the changes. – Margaret Bloom Dec 05 '16 at 21:01

1 Answers1

11

The ASSUME directive tells the assembler what segment register you are going to use to access a segment.

This "binding" is useful to automate some common patterns:

  1. It tell the assembler which segment register to use to access a variable.
    If you don't explicit a segment register during a memory access the assembler uses the ASSUMEd values to automatically add a segment override prefix to the instruction.
    If a segment has not been ASSUMEd to be pointed by any segment register, the assembler fails with an error if you try to load/store a variable inside that register.

  2. It tell the assembler with respect to which segment to calculate the offsets.
    If you specify a segment register in a memory access the assembler use the segment ASSUMEd for that segment register to calculate the offset of the memory access.
    Note that although DS is implicitly used by the CPU on every memory access, an explicit override with DS: is needed make clear the intention to use its segment as a base for the offset.

  3. The segment ASSUMEd by CS is the segment the code labels belong to.
    You can't jump/call a symbol unless it is in the segment ASSUMEd by CS.

Consider the program below, not intended to be run but just disassembled.

.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__

If you did't ASSUME CS the assembler would complain with

CS unreachable from current segment

because you were defining a label __START__ in a code segment not ASSUMEd anywhere.

Margaret Bloom
  • 41,768
  • 5
  • 78
  • 124
  • I am having difficulty with point 2. If I understand correctly, this would mean that if given `mov dx, WORD PTR ds:[test2]` the assembler would calculate the offset of `test2` relative to the start of the `_DATI` segment, giving 0010h. However, in my disassembly, I find that `test2` is calculated as being at offset 0000h (i.e., relative to `_DATI2`, not `_DATI`). I assembled the above listing (excluding the erroneous line) with both TASM 4.1 and MASM 6.14 and I am seeing the same results in both cases. Am I misunderstanding this point or do you know what could explain this discrepancy? – ntwk May 20 '22 at 15:36