Как работает x86 eflags bit 18 (проверка выравнивания)?(Относится к проверке на 386 против 486 и позже.) - PullRequest
5 голосов
/ 23 сентября 2011

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

Ответы [ 2 ]

4 голосов
/ 23 сентября 2011

Мое предположение очень простое: код не хочет подписываться. В случае, если проверка выравнивания не установлена, и вы ее установили, вы фактически включаете проверки выравнивания (когда настройка работает). А когда указатель стека не выровнен по 4-байтовой границе, угадайте, что произойдет? Вы получили доступ к памяти без выравнивания, что приводит к сигбусу. И если вы не хотите, чтобы этот недопустимый доступ к памяти происходил (поскольку вы просто хотите изменить бит для целей тестирования), вы должны позаботиться о том, чтобы все обращения во время тестирования принимали наихудший случай (а именно: вы его включили , и ваш стек был до этого не выровнен, потому что в этом нет необходимости, так как до сих пор проверки были отключены).

2 голосов
/ 23 сентября 2011

Нет регистра SX.Либо опечатка, либо ссылка на область памяти.

...