
- •Лучший курс лекций по лучшему языку программирования – языку ассемблера Блок управления памятью (mcb)
- •Программирование на Ассемблере для ibm pc
- •Программная модель 8086
- •Программная модель мп
- •Сегментная память
- •Вывод на экран
- •Вывод строки символов
- •Вывод на экран шестнадцатеричного числа
- •Процедуры
- •Ввод символов
- •Вывод на экран двоичного числа
- •Работа с дисковыми файлами
- •Префикс сегмента программы (psp)
- •Структура префикса программного сегмента.
- •Прерывания.
- •Табличные вызовы подпрограмм.
- •Макрокоманды.
- •Макроопределения.
- •Использование параметров в макроопределениях.
- •Директива local
- •Использование библиотек макроопределений.
- •Конкатенация. (&)
- •Директивы повторения.
- •Условные директивы.
- •Перечисление условных директив.
- •Пример использования ifnb.
- •Пример использования макроопределений.
- •Резидентные программы tsr (terminate and stay resident)
- •Защита резидентной программы от повторной загрузки.
- •Выгрузка резидентной программы.
- •Переключение стека в резидентной программе.
- •Обработчик прерываний от таймера
- •Контроллер прерываний и его программирование
- •Взаимодействие прикладных и системных обработчиков прерываний
- •Резидентный обработчик прерываний от клавиатуры с подключением до системного
- •Резидентный обработчик прерывания от клавиатуры с подключением после системного обработчика
- •Резидентный обработчик прерываний от клавиатуры с подключением как до, так и после системного.
- •Вывод на экран текста средствами bios
- •Режимы дисплея
- •Работа с видеобуфером.
- •Логическая организация текстового видеобуфера.
- •Программирование портов. Звук.
- •Программирование звукового канала таймера.
- •Интерфейс с Си
- •Программы с несколькими сегментами команд.
- •Программы с несколькими сегментами данных.
- •Директива assume. Инициализация сегментных регистров и замена сегментов.
- •Структуры и записи.
Директива assume. Инициализация сегментных регистров и замена сегментов.
В программе с помощью assume устанавливается соответствие сегмента команд text сегментному регистру CS и сегмента данных data1-сегментному регистру DS:
Assume CS:text, DS:data1
Директивы assume, которых в программе может быть любое количество, в принципе могут располагаться в любом месте программы, однако, обязательно до тех программных строк, в которых выполняется обращение описываемым в конкретной директиве сегментам, поэтому
assume CS:text
должен стоять в программе до любых программных строк и даже до объявления процедур. Что касается регистра DS , то, если это соответствие не описано в первой директиве assume, оно может быть описано позже, например:
assume DS:data1
fill: mov raw[BX],DL
Поскольку к моменту трансляции указанной выше команды mov, транслятор уже знает из директивы assume, что сегмент data1 сопоставляется с регистром DS, а имя raw описано именно в сегменте data1, команда транслируется в такой код, что процессор при его выполнении обратится к ячейке памяти с относительным адресом raw[BX], взяв сегментный адрес из регистра DS. Транслятор выполняет (не слишком строгую) проверку правильности ссылок на данные, так что если бы ячейка raw входила в другой сегмент, была бы зафиксирована ошибка. Т.о. описание в директиве assume соответствия сегментного регистра DS сегменту данных позволяет в какой то степени контролировать правильность написания программы и, главное, избавляет нас от необходимости указывать в каждой строке, содержащей ссылку на имя данных, в каком сегментном регистре находится сегментный адрес этих данных. По умолчанию подразумеваться регистр DS.
Однако из сказанного совершенно не следует, что к моменту выполнения команды mov в регистре DS будет в действительности находиться сегментный адрес соответствующего сегмента. Более того, его там и не будет, если мы об этом специально не позаботимся. Строки
mov AX,data1
mov DS,AX
Как раз и выполняют загрузку в сегментный регистр DS сегментного адреса нашего сегмента данных. Как мы уже знаем, при загрузке программы в память, оба сегментных регистра данных указывают на PSP, а совсем не на сегменты данных, так что до выполнения этих строк наш сегмент данных не адресуем.
Несколько по иному обстоит дело с дополнительными сегментами данных, к которым мы будем обращаться через сегментный регистр ES. Поскольку в программе регистр ES в директиве не описан, его следует указывать в явной форме во всех предложениях программы, где выполняется адресация к дополнительному сегменту данных data2:
mov ES:oddbit[DI],DL
….
Parity: mov ES:evenbit[SI],DL
Однако и в этом случае занесение в регистр ES требуемого сегментного адреса должно быть выполнено в программе явным образом, например
mov AX,data2
mov ES,AX
Директива assume создать умолчание и для регистра ES. Однако, для этого необходимо, чтобы дополнительный сегмент данных data2 был описан в программе до сегмента команд:
data2 segment
…
data2 ends
text segment ‘code’
. assume CS:text, DS:data1,ES:data2
.
. mov oddbit[DI],DL ;по умолчанию берется регистр ES , т.к.
;oddbit находится в data2
В этом случае директива assume ES:data2 избавляет нас от необходимости указывать в явной форме регистр ES во всех командах с обращением к данным из сегмента data2. Если таких строк много, то это несколько упрощает процесс написания программы. Некоторого улучшения можно достигнуть, заменив адресацию со смещением на чисто регистрово-базовую, индексную или базово-регистровую.
mov BX,offset raw;
…
fill: mov [BX],DL
mov SI, offset evenbit
mov DI, offset oddbit
pros: mov DL,[BX]
…
mov ES:[DI],DL
…
parity: mov ES:[SI],DL
Во всех 3-х массивах теперь пересчитываются не индексы внутри массивов, а смещение блоков массивов относительно начал соответствующих сегментов. Директива позволяет в некоторых случаях не указывать в командах программы сегментные регистры, однако она не запрещает это делать в случае необходимости. Часто к одному сегменту приходится обращаться то через один, то через другой сегментный регистр. Такая ситуация типична при выполнении команд обработки строк.
Источник ES:DI
Приёмник DS:SI
И потом источник и приёмник меняются местами
Здесь как бы не было объявлено соответствие сегментных регистров, придётся воспользоваться префиксом замены сегмента.
Директива assume может использоваться внутри программы неоднократно.
; Сегмент данных
data segment
mem1 DW ?
mem2 DW ?
data ends
;ПРОГРАММНЫЕ СТРОКИ В СЕГМЕНТЕ КОМАНД
assume DS:data
mov AX,mem1 ;команда будет выполняться
mov BX,mem2 ; как AX,DS:mem1
assume DS:nothing
assume ES:data ;команда будет выполняться
mov AX,mem1 ; как AX,ES:mem1
mov BX,mem2
Директива assume DS:nothing (ничего) снимает закрепление за сегментом data регистра DS и позволяет закрепить за сегментом другой регистр assume ES:data.
Очевидно, что независимо от директивы assume, перед первым участком необходимо настроить на сегмент data регистр DS, а перед вторым-ES.