the use of ASSUME directive in 8086 instruction set

BalaK picture BalaK · Feb 7, 2016 · Viewed 8.7k times · Source

In my textbook, its given that the ASSUME directive tells the assembler the names of the logical segments to use as the physical segments. And that it uses displacements from the start of the specified logical segment to code out instructions. Click here for the screenshot. But, here when i execute this assembly program in emu8086, it automatically determined the offsets/displacements (even after commenting out the ASSUME statement). How does it do that? So, ASSUME statement is redundant?

Answer

zx485 picture zx485 · Feb 7, 2016

So, ASSUME statement is redundant?

No. The ASSUME directive tells the assembler to assume, that a certain register contains the base of some structure(in your case: segments). In your case, CS and DS point to the code segment and the data segment respectively, both the one and only of their respective kind. So CS is already assumed as a pointer to the code segment, because the code segment is the only one. So is DS.

If you would change, for example, DS with mov ax, 2000h ; mov ds, ax to a hypothetical second data segment located at (segment) address 2000h, some references to the content can be mislead. The follwing code snippets are not correct and would not assemble, their sole purpose is to illustrate the difference!

data_here segment
  multiplier     db 02h
  multiplicand   db 08h
  product        dw dup(0)       ; ??? btw, missing a count between dw and dup(0) ?
data_here ends

and

data_there segment
  ihavesomevalue dw 1234h
  multiplier     db 02h
  multiplicand   db 08h
  product        dw dup(0)       
data_there ends

The difference between here and there, between assume ds:data_here and assume ds:data_there, is the following:

lea ax, data_here
mov ds, ax
assume  ds:data_here
mov cx, word ptr [multiplier]

leads to CX containing 0802h (multiplier + multiplicand in LSB order). Now pointing DS to data_there and assuming data_here:

lea ax, data_there       ; MODIFIED !!!
mov ds, ax
assume  ds:data_here
mov cx, word ptr [multiplier]

would lead CX to contain 1234h - the value of ihavesomevalue.

Why is this so?

Well, DS is assumed as data_here in both cases.

But in the first case the assumption, that DS is pointing to data_here is correct and so the indices of the variables/data bytes do fit.

In the second case, DS is pointing to data_there. But the assembler is misleaded to the assumption, that DS is also pointing to the segment data_here. So the index of the variable multiplier is 2 instead of 0 and therefore the value is accessed at the wrong place. Hence the different result.

An inappropriate application of the assume directive can create hard-to-detect bugs.

BTW, the assume directive can be used for convenience purposes like generalizing the access to structures in registers which will increase the readability of code:

BLOCK struct
  item1 dd 0
  item2 dd 0
  item3 dd 0
BLOCK ends

This structure can be accessed by

assume esi:PTR BLOCK 
mov eax, [esi].item2
add ecx, [esi].item3

and so on. In the above cases ESI is considered/assumed to be a pointer to a BLOCK structure, so the indices are generated appropriately.

P.S.: Welcome to Stack Overflow!