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?
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.
8086 uses the directive SEGMENT(segment) to identify the beginning of a segment. The name of the segment should precede the keyword SEGMENT (segment). A segment thus declared will contains the code or the data depending on whether the declared segment is code segment or data segment.
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: It tell the assembler which segment register to use to access a variable.
IN this program SEGMENT, DB, ENDS, ASSUME, END, and ENDP are examples of directives.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With