3.Адресация памяти в реальном режиме. Преобразование сегмента и смещения в физический адрес. Ближние и дальние указатели. Сегменты данных.

Формирование адреса в реальном режиме

Основная идея сегментной адресации в том, что адрес состоит из двух частей — сегментной и смещения. Обычно их записывают через двоеточие (например 0100:0500). Линейный адрес любой ячейки памяти получается в результате сложения смещения и сегментной части, сдвинутой на 4 бита влево.

Начало сегмента всегда выровнено на границу параграфа (адрес кратен 16 байтам). Максимальный размер сегмента равен 2^16 = 64 КБайта. А всего можно адресовать 2^20 = 1 МБайт памяти.

Одна из особенностей сегментной адресации — неоднозначность представления адреса. Допустим, требуется обратиться к ячейке памяти по адресу 00400. Этот адрес может быть представлен как 0000:0400, 0040:0000, 0020:0200 и так далее.

Загруженная в память программа может одновременно работать с четырьмя сегментами. Сегменты могут перекрываться или даже совпадать, как это было в случае с COM-программой.

Для всех команд подразумевается сегмент «по умолчанию». Например, команды PUSH и POP работают с сегментом стека. Если операнд такой команды находится в памяти, то он берётся из сегмента данных. Команды JMP и LOOP вычисляют адрес перехода в сегменте кода.

Дальние переходы, вызовы процедур и возвраты

Дальними (far) называются переходы в другой сегмент кода. При их выполнении меняется содержимое регистра cs. Они могут только безусловными. Ближние (near) переходы осуществляются в пределах одного сегмента. Аналогично есть дальние и ближние вызовы процедур, а также дальние и ближние возвраты.

Команда дальнего вызова процедуры сохраняет в стек не только ip, но и cs, чтобы можно было вернуться в текущий сегмент кода. Команда RET является синонимом ближнего возврата RETN. Дальний возврат осуществляется командой RETF. Она восстанавливает из стека регистры ip и cs.

Директивы управления сегментами и моделями памяти макроассемблера MASM

В макроассемблер MASM (в тасме тож фурычит) включены директивы, упрощающие определение сегментов программы и, кроме того, предполагающие те же соглашения, которые используются в языках высокого уровня Microsoft. Упрощенные директивы определения сегментов генерируют необходимый код, указывая при этом атрибуты сегментов и порядок их расположения в памяти. Везде в этой книге мы будем использовать именно упрощенные директивы определения сегментов, наиболее важные из которых перечислены далее: