popad

2026-02-27 13:51
vak: (Знайка)
[personal profile] vak
Вот пример смешных вещей, которые выясняются при тестировании процессорных инструкций. Есть в i386 команда POPAD. Когда мы находимся в 32-битном режиме, она выпихивает из стека значения восьми 32-битных регистров. Но значение ESP игнорирует, чтобы не нарушать стек. Это всё подробно описано и надёжно работает.

Но у команд i386 ещё бывают префиксы. Например префикс 0x67 меняет разрядность адресов в команде. В данном случае команда продолжает выпихивать 32-битные значения, но к стеку обращается по 16-битным адресам. Старшая половина ESP[31:16] игнорируется.

Вопрос: что происходит с этой старшей половиной ESP в результате выполнения команды POPAD с префиксом 0x67?

В документации вы прочитаете, что старшая половина регистра стека не изменяется. Это неправда. Как показывают тесты, биты ESP[31:16] получают значение из стека, как и прочие регистры. Был стек ESP=0x00005E90, стал 0x5A045EB0. Неожиданность! Как говорится, это нельзя объяснить, можно только запомнить. 😀

Date: 2026-02-28 02:27 (UTC)
spamsink: (Default)
From: [personal profile] spamsink
Привет УИМ М17.

Date: 2026-02-28 05:12 (UTC)
archaicos: Шарж (Default)
From: [personal profile] archaicos
Прикол. Должна быть какая-то errata. И возможно в более новых процессорах это исправлено.

Date: 2026-02-28 12:16 (UTC)
From: [personal profile] litwr
Интересно, а как вы тестировали в этом режиме? Из ДОС выйти в 32-разрядный режим - это морока, нужно дескриптор подготовить и т.п. А современные системы работают в режиме 64-бита...

Date: 2026-03-01 07:32 (UTC)
From: [personal profile] litwr
Ассемблер x86 устроен так, что явно использовать префиксы разрядности почти (а может и совсем) никогда не надо. В ДОС POPA с префиксом OS - это POPAD, у POPAD и POPA один и тот же код. А вот как тут понять префикс AS (067h) мне не совсем понятно. В ДОС адреса 16-битные и AS меняет их на 32-битные. Но мой код вроде показывает, что этот префикс на POPA/POPAD не действует, в 32-битном режиме всегда используется ESP, что позволяет предположить, что в 16-битном всегда используется SP.
Проверил код в DOSBox - аномалий нет, а префикс AS ни на что не влияет.
Интересно каким кодом вы обнаружили аномалию?

Date: 2026-03-01 09:08 (UTC)
From: [personal profile] litwr
Извините, но как это запускается? У автора как-то для меня неясно. И есть ли исходники?
И там упоминается, что используют LOADALL, который с 486 отменили совсем. У меня где-то валяется старая платка с 386, жалко выбрасывать - в 1993 привезли для меня из США по спецзаказу! Может попробую с ней.

Date: 2026-03-01 10:28 (UTC)
From: [personal profile] litwr
Но в файле почти 4 МБ! Что и куда заносятся? Где значения указаны? Что это за формат MOO? Команда file про него не знает. :(

Date: 2026-03-01 12:59 (UTC)
From: [personal profile] litwr
Дошло откуда что берётся, тормозил разрыв между размером му-файла и приведенным отчетом. Такое можно и из ДОС или может лучше забить в бут-код системы. Наверное для совместимости со всеми 386+ следует вместо рекомендуемой LOADALL использовать нереальный режим для установки лимитов на адреса в реальном режиме. Может и попробую запустить, но явно не сейчас. C установкой некоторых флагов и регистров могут быть тонкости.

Date: 2026-02-28 13:37 (UTC)
From: [personal profile] litwr
Сделал тест под Линукс и аномалий не обнаружил. ОС 64-бита, но Линукс, как и Винда, нормально работает с 32-битным кодом. Код тут. Наверное тут зависимость от конкретной марки и производителя.

Date: 2026-02-28 19:07 (UTC)
From: [personal profile] litwr
Немного изменил код, меняя значение ESP в стеке на 0, но эффект прежний - аномалий нет, ESP никак не меняется после POPAD.

Date: 2026-03-03 13:08 (UTC)
From: [personal profile] litwr
Запустил на 386DX@25MHz - баг подтвердился! Интересно его хоть где-то задокументировали? И, интересно, а как вы получили данные прогонов с реального железа? Эти му-тесты вроде сделаны для эмуляторов и не очень хороши для штатных ПК. Ещё у этих му-тестов непонятно в каком они режиме: 16- или 32-битном. :(
Ну и запутали вы с префиксом AS... ;)
Сделал ещё код для загрузочного сектора, он поддерживает 32-битную адресацию в 16-битном режиме, но как оказалось это для выявления аномалии было лишним.
На Целероне и почти современной Аэмдешке всё правильно - аномалия не проявляется.
Трудно представить, что на этом баге кто-то мог спотыкнуться. Старшие разряды ESP всё равно не используются в ДОС. Это не тот кошмар, как с известным POPAD-багом, когда ломается всё. Похоже тот, кто ваял POPAD, или спешил, или ещё что-то.
Edited Date: 2026-03-03 13:09 (UTC)