2013-06-26 8 views
5

После компиляции приведенных ниже кодов функция не работает должным образом.Почему условное перемещение не работает должным образом

int cread(int *xp){ 

    return (xp?*xp:0); 

} 

Я извлекаю экземпляр в монтажной версии, как показано ниже.

xp в регистре %edx

movl $0, %eax 
testl %edx, %edx 
cmovne (%edx), %eax 

Может кто-нибудь сказать мне, почему указатель xp еще был де-ссылается cmovne даже когда тест терпит неудачу? не является ZF, установленным на 1 по testl инструкцией, когда %edx является 0?

+1

А? 'cmovne' - это« перемещение, если оно не равно нулю », т. е.« двигаться, если ZF == 0 »; разыменование не происходит, если '% edx' равно 0. –

+0

Просто уточнение терминологии; это «move if not equal» (иначе «cmovnz' -« move if not zero »). – Michael

ответ

3

Руководства по набору инструкций Intel, похоже, указывают, что операнд CMOV не читается, если условие не выполняется. (Я подозреваю, что «алгоритм» для инструкции, приведенной в руководстве, не совсем прав.)

По-видимому, другие люди не согласны; см. явное предостережение here:

Если операнд-источник является операндом памяти, он всегда читается независимо от того, выполняется ли условие. Это означает, что любое исключение было бы создано из чтения памяти, будет генерироваться. Если чтение памяти вызвало бы #GP или #PG, то пусть будет так.

Я подозреваю, что аргументация заключается в следующем: декодер команд считывает инструкции, вычисляет эффективные адреса и выдает память как можно раньше, задолго до того, как инструкция будет полностью декодирована и готова к выполнению. Таким образом, чтение в память получает запланированное/выполняемое раньше и вызывает ловушку. Только до тех пор, пока CMOV не будет достигнут исполнительным блоком, что он знает, что чтение памяти не требуется, и запуск его, который в последнее время сделает инструкцию очень медленной, а также усложнит логику предварительной выборки команд.

Я использую его только в своей регистрационной форме, которая не может ловушку.

+0

Если это действительно так, то это не ошибка со стороны компилятора, чтобы испустить его в контексте OP? –

+0

@ 500-InternalServerError: да, похоже, что это была бы ошибка компилятора. Они не всегда идеальны: - { –

+0

На самом деле у меня есть другой вопрос, как компилятор решает, подписан ли операнд инструкции или нет, и затем соответствующим образом установите регистры условного кода. – JDein

Смежные вопросы