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-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.