Консультация № 191723
10.11.2017, 19:46
0.00 руб.
0 6 1
Уважаемые эксперты! Пожалуйста, ответьте на вопрос:

почему "Многие уже, наверное, заметили, что при запуске какой-нибудь COM-программы регистр sp равен 0FFFEh"? А не 0FFFFh?

Обсуждение

давно
Посетитель
7438
7205
10.11.2017, 20:08
общий
Адресаты:
На 16-битной машине регистр SP - 16-битный. Для работы с ним будет намного лучше, если и адресуемая память будет выровнена на 16 бит, т.е. на четное значение. Строго говоря, будет работать и с нечетной границей, но тогда при обращении к памяти будет тратиться лишний такт. Как-то неправильно и неэффективно. Именно поэтому память желательно выравнивать на необходимую величину. ОС и отладчики это делают автоматически.
То же самое относится и к 32- и 64-битным программам, где память желательно выравнивать , соответственно, на 4 и 8 байт.
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Старший Модератор
312929
1973
11.11.2017, 05:14
общий
Адресаты:
Тем более, что в современных процессорах Intel (начиная ещё с 80486) предусмотрен режим контроля выравнивания, в котором любая команда, обратившаяся по адресу, не кратному размеру аргумента, вызывает прерывание.
давно
Старший Модератор
31795
6196
13.11.2017, 10:51
общий
Адресаты:
Когда компьютеры были большими, а ресурсов(памяти) мало, а 64-Кб кода так много(практически это 20 000 строчек кода). Разработчиками ОСей был придуман стандарт СОМ-файлов:код, данные и стек находятся в одном сегменте. В таких программах не нужно было настраивать сегменты и остальное что с этим связано. В целях экономии памяти носителей информации, система сама подставляла стандартный префикс программы(это аж 256-ть байт на каждую программу пользователя) и заносила в стек 0х0000(как метод защиты самой себя).
Смотрите пример с ошибкой:
[code lang=asm]model tiny
.code
org 100h
begin:
;какой то код пользователя
;вызов подпрограммы с ошибкой
call pppp
;вывод сообщения пользователю
mov ah,9
lea dx,dbMes
int 21h
;завершение программы
ret
pppp:
;какой то код подпрограммы
;ошибка пользователя - нарушение стека
pop ax
;какой то код и возврат из подпрограммы
ret
;сообщение пользователю
dbMes db 10,13,'message$'
end begin[/code]
Теперь пусть программист думает, почему сообщение не было выведено, а код завершился. При выполнении очередной команды выхода из подпрограммы - RET, управление передается по адресу CS : 0000, а там INT 20h - завершить СОМ-программу, а не непонятно куда.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
7438
7205
14.11.2017, 11:33
общий
Адресаты:
Здесь все понятно?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
401455
7
15.11.2017, 23:12
общий
Адресаты:
СПАСИБО за консультации.
Данный вопрос Консультация онлайн # 191723, можно закрывать. В общих чертах - понятно! Мой уровень - "Hello! World!", поэтому ваш ответ от 10.11.2017, 21:08 - "... память желательно выравнивать на необходимую величину. ОС и отладчики это делают автоматически", мне более понятен. Пока этого достаточно!
давно
Посетитель
7438
7205
20.11.2017, 11:49
общий
это ответ
Здравствуйте, kerenskyaf!
Четное значение вершины стека в 16-битном режиме процессора, а ДОС-овские программы работают именно в 16-битном режиме,
необходимо для выравнивания адреса на слово. Процессоры х86 так устроены, что они работают лучше всего, если адреса памяти выровнены на разрядность процессора.
Обычно выравнивание памяти происходит компиляторами (при компиляции) и ОС (при выполнении) автоматически.

Строго говоря, в незащищенном 16-битном режиме будет работать и с нечетной границей, просто при обращении к памяти будет тратиться лишний такт.
А вот в защищенных 32- и 64-битных режимах (в Windows или Linux) предусмотрен режим контроля выравнивания, при котором произойдет исключение, т.е. аварийное завершение. Отсюда, в 32- и 64-битном режимах точно необходимо выравнивать память на 4 и 8 байт соответственно.

Именно поэтому память, и особенно стек, желательно выравнивать на необходимую величину.

Как справедливо заметил Зенченко К.Н.:
Само значение 0xFFFE получается потому, что при запуске программы значение вершины стека SP = 0
Потом загрузчик программы выполняет команду PUSH 0, чтобы в стеке оказался адрес 0,
по которому в начале программного сегмента записывается команда int 20h.
Это сделано, чтобы работала команда ret, по которой перейдет управление как раз на адрес 0 и выполнится int 20h
А после выполнения PUSH 0 и получается, что SP = 0xFFFE
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Форма ответа