Сборка x86 - CMP неправильно устанавливает нулевой флаг

Я столкнулся с этим сравнением при отладке:

| 38 19 | CMP BYTE PTR DS:[ECX], BL

Я установил на нем точку останова и увидел это (значения в hex):

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 и приводит к неправильным результатам.


person Saduff    schedule 19.01.2017    source источник
comment
Обычно CMP устанавливает флаги правильно, и значения, которые вы показали, указывают на то, что ZF должен быть установлен, поэтому я на 99% уверен, что одно из описанных вами значений неверно. Я бы сначала проверил содержимое памяти, вы уверены, что в ds:[ecx] есть 55? Как вы получили этот номер? Это режим 32b с плоской моделью памяти (ds = тогда не важно)?   -  person Ped7g    schedule 19.01.2017
comment
Помните, что CMP правильно устанавливает флаги. Вините код, а не процессор.   -  person Weather Vane    schedule 19.01.2017
comment
Ну, технически у вас может быть поврежден ЦП, выдающий неверные флаги после CMP, но если это не одноразовая ошибка блуждающего электрона из-за рентгеновского столкновения и т. д. (может случиться, с количеством HW в повседневной жизни есть шанс, что по крайней мере несколько ныне живущих людей хотя бы раз в жизни столкнутся с такой ситуацией ... хотя они, скорее всего, не заметят), это произвело бы так много плохих результаты, что вы никогда не дойдете до загрузки вашей ОС и запуска отладчика ... Так что, если вы не верите cmp, попробуйте еще раз, и все, ищите проблему вокруг.   -  person Ped7g    schedule 20.01.2017


Ответы (1)


Я подозревал, что в отладчике какая-то ошибка, поэтому попробовал с другим (OllyDbg v2) и увидел, что введенные мной значения действительно правильные, в памяти и в BL было 55. Однако, работая под Olly, CMP вел себя правильно, как и ожидалось, то есть ZF был установлен, а прыжок не был выполнен.

Так что код на самом деле работает как задумано, проблема в отладчике. Когда код не работает под отладчиком, он также работает корректно. Для этого конкретного кода проверить правильность без отладчика немного сложно и требует много времени, поэтому я до сих пор никогда не тестировал его без отладчика. Ошибка не связана с точкой останова или пошаговым выполнением, поскольку она также не работала правильно при простом запуске.

Отладчик с ошибкой - x64dbg (несмотря на название, он не только для 64-битной). Моя сборка уже немного устарела, возможно баг исправлен в последнем снапшоте.

Спасибо всем за комментарии.


На самом деле это была ошибка пользователя, а не ошибка в отладчике. Была точка останова INT3, установленная на 00838430, о которой я забыл, или, может быть, я на мгновение забыл, как работают программные точки останова. Так или иначе, фактическое содержимое памяти в этом случае было 0xCC, но отладчик показал исходный байт. Так что CMP вел себя именно так, как должен был. Ped7g был прав с первого комментария, что я должен перепроверить содержимое памяти. Второй тест с другим отладчиком работал правильно только потому, что я тогда не поставил точку останова на 00838430.

https://i.imgur.com/iWKad22.jpg

person Saduff    schedule 19.01.2017