Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does ASSUME mean in assembler?

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

like image 510
Dmitriy Nalivajko Avatar asked Dec 24 '22 23:12

Dmitriy Nalivajko


1 Answers

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.

like image 174
Margaret Bloom Avatar answered Feb 18 '23 08:02

Margaret Bloom