Может кто-нибудь помочь мне с сегментацией и микропроцессором Intel 8086?

Я читаю об архитектуре Intel 8086 и не могу понять следующее о сегментации: я знаю, что регистры сегментов указывают на сегменты соответственно и содержат базовый адрес длинного сегмента 64 КБ. Но кто вычисляет и в какой точке устанавливает физический адрес в сегментных регистрах? Кроме того, поскольку один физический адрес может быть доступен нескольким сегментам: пары смещений и сегменты могут перекрываться, как вы можете быть уверены, что не будете перезаписывать что-либо? Где я могу прочитать больше об этом?

1 ответ

Решение

Вообще говоря, Ассемблер будет использовать только смещенные адреса для доступа к логическому адресу. Например, глядя на этот код:

start   lea si,[hello]          ; Load effective address of string
        mov word [ds:si+10],0   ; Zero-terminate string after 10th letter
        jmp $                    ; Loop endlessly

; Fill rest of the segment with 0s
times 65536-($-$$) db 0x00

hello   db "I'm just outside of the current segment. Hello!",0

Ассемблер попытается вычислить смещение 'hello' от источника программы. Так как происхождение не определено, будет принято 0x0. Однако смещение 'hello' в этом случае будет 0x10000, что не соответствует 16 битам. Для этого Ассемблер урезает адрес до 0x0000. Это не изменит ни один из регистров сегмента. Однако, вероятно, он выдаст предупреждение, например, test.asm:1: warning: word data exceeds bounds, Что на самом деле происходит при запуске этой программы, так это то, что jmp $ строка перезаписывается нулями, потому что адрес hello обернут, и процессор начнет выполнять только нули, а это не то, что вы намеревались сделать.

Это, конечно, только если сегмент кода и сегмент данных совпадают. Теперь, кто гарантирует, что это так? Никто на самом деле. Тем более, что я до сих пор не знаю, для какой платформы вы кодируете. Вы должны полностью настроить регистры сегментов с правильными значениями. Самый простой способ сделать это:

push cs   ; Push address of code segment to stack
pop ds    ; Pop address back into data segment
push cs   ; Same for extra data segment
pop es    ;

Таким образом, вы можете быть уверены, что получаете доступ к смещению в сегменте правильных данных.

Теперь о том, "Как вы убедитесь, что сегмент кода не перекрывает сегмент данных", почему бы и нет? Когда ваша программа с данными меньше 64 КБ, на самом деле это самый простой способ доступа к данным, если ваш код и сегмент данных идентичны.

И как вы можете быть уверены, что не перезаписали ничего важного? Ассемблер не может вам в этом помочь, вы должны проверить сами, содержит ли сегмент: смещенный адрес, на который вы пишете, данные.

Другие вопросы по тегам