Я читал, что если Бит 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. Я решил исправить комментарии, чтобы не запутывать людей подобными вопросами.