Я читал, что если бит флагов 18 (проверка выравнивания AC) может быть изменен, вы знаете, что CPU - это 486 или более новый. На 386 бит поддерживает модификацию.Как работает x86 eflags бит 18 (проверка выравнивания)? (Связано с проверкой на 386 по сравнению с 486 и более поздними версиями.)
Я поднял следующий код сборки из this site и добавил исчерпывающие комментарии (оставляя нечетные синтаксис нетронутыми):
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, если аль регистр установлен в 1 в конце (считая с самого начала, что он не старше), и это 486 или новее в противном случае. Я понимаю эту часть.
Что я не понимаю, почему указатель стека должен быть усечен до 4-байтовой границы перед выполнением теста модификации флага? Я предполагаю, что он предназначен для установки бит 18, поскольку это бит выравнивания в конце концов ... но xor с 0x40000 будет переворачивать бит независимо от его значения. Другими словами, тест модификации должен иметь тот же результат независимо от начального значения, правильно?
Если ответ отрицательный, я думаю, что [лучший] [необразованный] предположил, что «почему»: «Может быть, следующие команды push/pop могут привести к выравниванию? Это приведет к выравниванию ранее не выровненного указателя стека и приведет к переводу бита выравнивания от 0 до 1. В этом случае успешная модификация окажется неудачной, и наоборот ». (EDIT: Это определенно неверно, потому что бит выравнивания - это принудительное исполнение, а не отслеживание выравнивания. Кроме того, я сомневаюсь, что pop/push в любом случае приведет к выравниванию ранее не выровненного стека).
Даже если это так, какова цель выравнивания указателя стека снова после теста (прямо перед восстановлением исходных флагов и указателя стека)? Разве это уже не должно быть на 4-байтной границе раньше? Если нет, то как это могло измениться после нажатия/выталкивания 4-байтных значений?
Короче говоря, некоторые из инструкций кажутся излишними для меня, и я чувствую, что мне не хватает чего-то важного. Может ли кто-нибудь объяснить это?
(Боковой вопрос: самая первая строка копирует значение из «sx» в bx. Я никогда не видел ссылки на регистр sx где-нибудь. Действительно ли это существует или это опечатка? ключ довольно далеко от ключа «p», по крайней мере, на американских клавиатурах.)
EDIT: Теперь, когда на этот вопрос был дан ответ, я решил удалить неверный комментарий из двух строк выравнивания в коде. Я изначально сделал предположение, что выравнивание стека установит бит выравнивания, и я написал это в свой комментарий (остальная часть вопроса продолжается с этой неправильной логикой). Вместо этого бит проверки выравнивания действительно заключается в обеспечении выравнивания (а не отслеживании), как указывает ответ flolo относительно sigbus. Я решил исправить комментарии, чтобы не путать людей с подобными вопросами.
В каком музее вы ворвались, чтобы найти 386? Тебе лучше вернуть его обратно. –
LOL! Насколько я знаю, я никогда не прикасался к рабочему столу 386 ... Я перепутал с старым 286 в тот же день, но я пропустил это прямо к Pentium 75. Я просто решил закрыть свои базы, прежде чем вызывать инструкцию CPUID (сначала убедитесь, что у вас нет 386, а затем проверьте бит флэш-бит 21 на наличие CPUID), в случайном случае какой-то сумасшедший когда-либо решил использовать мой код на древнем оборудовании. Наверное, я просто анал ... но по крайней мере я не проверяю 8-битные и 16-битные процессоры, поскольку современные компиляторы, по-видимому, даже не генерируют код для них. ;) –