Как работает x86 eflags бит 18 (проверка выравнивания)? (Относится к проверке 386 по сравнению с 486 и более поздними версиями.)

Я читал, что если Бит 18 eflags (AC - проверка выравнивания) может быть изменен, вы знаете, что процессор - 486 или новее. На 386 бит сопротивляется модификации.

Я взял следующий код сборки с этого сайта и добавил исчерпывающие комментарии (оставив нечетный синтаксис без изменений):

asm
    mov  bx,sx            ; Save the stack pointer to bx (is sx a typo or a real register?).
    and  sp,$fffc         ; Truncate the stack pointer to a 4-byte boundary.
    pushfl                ; Push the eflags register to the stack.
    pop  eax              ; Pop it into eax.
    mov  ecx,eax          ; Save the original eflags value into ecx.
    xor  eax,$40000       ; Flip bit 18 in eax.
    push eax              ; Push eax to the stack.
    popfl                 ; Pop modified value into eflags.
    pushfl                ; Push eflags back onto the stack.
    pop  eax              ; Pop it into eax.
    xor  eax,ecx          ; Get changed bits from the original value.
    setz al               ; Set al register to 1 if no bits changed (0 otherwise).
    and  sp,$fffc         ; Truncate the stack pointer to a 4-byte boundary.
    push ecx              ; Push ecx (original eflags) to stack.
    popfl                 ; Pop it into eflags to restore the original value.
    mov  sp,bx            ; Restore the original stack pointer.
end ['eax','ebx','ecx'];

ЦП - это 386, если регистр al установлен в 1 в конце (при условии, что с самого начала он не старше), и это 486 или новее в противном случае. Я понимаю эту часть.

Что я бы сказал Не понимаю, почему указатель стека должен быть усечен до 4-байтовой границы перед выполнением теста модификации флага? Я предполагаю, что он предназначен для установки бита 18, поскольку в конце концов это бит выравнивания ... но xor с 0x40000 перевернет бит независимо от его значения.Другими словами, тест модификации должен давать один и тот же результат независимо от начального значения, верно?

Если ответ отрицательный, мое лучшее [необразованное] предположение относительно «почему»: «Может быть, следующие инструкции push / pop может принудительно выполнить выравнивание? Это приведет к выравниванию ранее невыровненного указателя стека и заставит бит выравнивания самостоятельно переключиться с 0 на 1. В этом случае успешная модификация будет казаться неудачной, и наоборот ». (РЕДАКТИРОВАТЬ: это определенно неверно, потому что бит выравнивания предназначен для обеспечения, а не отслеживания выравнивания. Кроме того, я сомневаюсь, что pop / push все равно принудит выравнивание в ранее невыровненном стеке.)

Даже если это так, что цель повторного выравнивания указателя стека после теста (прямо перед восстановлением исходных eflags и указателя стека)? Разве это не должно быть уже на 4-байтовой границе раньше? Если нет, то как это могло измениться от нажатия / извлечения 4-байтовых значений?

Короче говоря, некоторые инструкции кажутся мне избыточными, и я чувствую, что, должно быть, упускаю что-то важное. Может ли кто-нибудь здесь объяснить это?

(Дополнительный вопрос: самая первая строка копирует значение из "sx" в bx. Я никогда нигде не видел ссылки на регистр sx. Он действительно существует или это опечатка Клавиша «x» довольно далека от клавиши «p», по крайней мере, на клавиатурах США.)

РЕДАКТИРОВАТЬ: Теперь, когда на этот вопрос был дан ответ, я решил удалить неправильный комментарий из двух строк выравнивания в код.Первоначально я предположил, что выравнивание стека установит бит выравнивания, и я написал это в своем комментарии (остальная часть вопроса продолжается с этой неправильной логикой). Вместо этого бит проверки выравнивания действительно предназначен для обеспечения выравнивания (а не для его отслеживания), как указывает ответ flolo относительно sigbus. Я решил исправить комментарии, чтобы не запутывать людей подобными вопросами.

5
задан Mike S 23 September 2011 в 16:15
поделиться