Везде это объясняется как вещь, которая связывает/ассоциирует регистры с сегментами, но я хочу понять, что именно связано.
Что означает ПРЕДПОЛАГАЕТСЯ в ассемблере?
Ответы (1)
Директива ASSUME
сообщает ассемблеру, какой сегментный регистр вы собираетесь использовать для доступа к сегменту.
Эта «привязка» полезна для автоматизации некоторых распространенных шаблонов:
Он сообщает ассемблеру, какой сегментный регистр использовать для доступа к переменной.
Если вы не указываете сегментный регистр во время доступа к памяти, ассемблер использует значенияASSUME
d для автоматического добавления префикс переопределения сегмента к инструкции.
Если сегмент не былASSUME
d указан ни в одном сегментном регистре, ассемблер выдаст ошибку, если вы попытаетесь загрузить/сохранить переменную внутри этого регистра.Он сообщает ассемблеру, относительно какого сегмента вычислять смещения.
Если вы указываете сегментный регистр в доступе к памяти, ассемблер использует сегментASSUME
d для этого сегментного регистра, чтобы вычислить смещение доступ к памяти.
Обратите внимание, что хотяDS
неявно используется ЦП при каждом доступе к памяти, необходимо явное переопределение с помощьюDS:
, чтобы было ясно намерение использовать его сегмент в качестве основы для смещения.Сегмент
ASSUME
d поCS
— это сегмент, к которому принадлежат кодовые метки.
Вы не можете перейти/вызвать символ, если он не находится в сегментеASSUME
d поCS
.
Рассмотрим приведенную ниже программу, не предназначенную для запуска, а только дизассемблированную.
.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 недоступен из текущего сегмента
потому что вы определяли метку __START__
в сегменте кода, а не ASSUME
d нигде.