Сборка x86 - CMP неправильно устанавливает нулевой флаг
Я наткнулся на это сравнение при отладке:
| 38 19 | CMP BYTE PTR DS:[ECX], BL
Я установил точку останова и увидел это (значения в шестнадцатеричном формате):
ECX = 00838430
BYTE PTR[ECX]=[00838430]=55
EBX = 00000055 (BL = 55)
EFLAGS = 00000314 (CF=0 OF=0 SF=0 ZF=0 AF=1 PF=1)
Поэтому я ожидал, что после выполнения этого сравнения будет установлен нулевой флаг, поскольку байты, на которые указывают ECX и BL, равны. Однако вместо этого был установлен флаг переполнения, а ZF остался 0. После сравнения:
EFLAGS = 00000A06 (CF=0 OF=1 SF=0 ZF=0 AF=0 PF=1)
Почему это ведет себя так? Это как-то связано со знаковыми / беззнаковыми целыми числами? Я думал, что CMP был независимым, то есть интерпретация результата сравнения как подписанного / неподписанного была бы чем-то, что сделала бы следующая инструкция ветвления (например, JG против JA). За сравнением следует JNE, который берется из-за того, что ZF=0 и приводит к неверным результатам.
1 ответ
Я подозревал, что в отладчике была какая-то ошибка, поэтому я попытался с другой (OllyDbg v2) и увидел, что значения, которые я отправил, действительно были правильными, их было 55 в памяти и в BL. Тем не менее, работая под Олли, CMP вел себя правильно, как ожидалось, то есть ZF был установлен, а переход не был выполнен.
Так что код на самом деле работает так, как задумано, проблема в отладчике. Когда код не работает под отладчиком, он также работает правильно. Для этого конкретного кода немного сложно и много времени проверить правильность без отладчика, поэтому до сих пор я никогда не проверял его без отладчика. Ошибка не с точкой останова или пошаговым выполнением, так как она не работала корректно при запуске.
Отладчик с ошибкой - x64dbg (несмотря на название, он не только для 64-битных). Моя сборка уже немного устарела, возможно, ошибка исправлена в последнем снимке.
Всем спасибо за комментарии.
Это была ошибка пользователя, а не ошибка в отладчике. Была точка останова INT3, установленная на 00838430, о которой я забыл или, может быть, на секунду забыл, как работают программные точки останова. В любом случае, фактическое содержимое памяти в этом случае было 0xCC, но отладчик показал исходный байт. Таким образом, CMP вел себя именно так, как и должен был. Ped7g был прав с первого комментария, что я должен перепроверить содержимое памяти. Второй тест с другим отладчиком работал правильно только потому, что тогда я не установил точку останова на 00838430.