Как в сборке x86 установить нулевой флаг (ZF) без операции сравнения?

У меня есть короткий фрагмент сборки (x86), который я пытаюсь понять, что он делает.

...
 6:     81 ec 00 01 00 00       sub    $0x100, %esp
 c:     31 c9                   xor    %ecx  , %ecx
 e:     88 0c 0c                mov    %cl   , (%esp, %ecx, 1)
11:     fe c1                   inc    %cl
13:     75 f9                   jne    0xe
....

Похоже, что он зацикливается до тех пор, пока "JNE" не будет оценен как false, то есть нулевой флаг = 0. (возможно, он помещает числа 1, 2, 3... в стек??)

Из моего краткого исследования сборки (я новичок в этом) видно, что вы устанавливаете нулевой флаг, выполняя операцию сравнения (CMP), но я не вижу операции сравнения.

Итак, при каких условиях он вырвется из этой петли?


person Robert    schedule 06.12.2011    source источник


Ответы (4)


inc устанавливает ZF, если значение cl после приращения равно нулю. Ваш цикл делает это:

sub    $0x100, %esp            // unsigned char array[256];
xor    %ecx  , %ecx            // unsigned char cl = 0;
mov    %cl   , (%esp, %ecx, 1) // e: array[cl] = cl;
inc    %cl                     //    cl += 1;
jne    0xe                     //    if (cl != 0) goto e;

Цикл завершается, когда cl увеличивается с 255 до 0, устанавливая ZF.

person Stephen Canon    schedule 06.12.2011
comment
Хорошо, это имеет смысл. Благодарю вас! - person Robert; 06.12.2011
comment
Думаю, я следил за всем этим, кроме mov %cl, (%esp, %ecx, 1). На английском языке я бы сказал, переместите младшие 8 бит CX (CL) в ОЗУ по адресу ESP+ECX, что имеет смысл, но что такое операнд 1? Это действительно array[cl + 1] = cl (переполнение стека?) или, может быть, array[cl] = cl + 1? Возможно я упускаю какой-то нюанс сборки x86, но мне любопытно. - person mpontillo; 06.12.2011
comment
1 на самом деле является размером, на который можно масштабировать смещение. Так что это действительно array[cl * 1] = cl. - person Stephen Canon; 06.12.2011
comment
@Mike: Обратите внимание, что это просто mov [esp+ecx], cl в синтаксисе Intel. - person GreyCat; 23.09.2014
comment
@GreyCat, педантично [esp+1*ecx] (без смещения, а не disp8=0 или disp32=0), хотя в данном случае это не совсем двусмысленно, поскольку esp нельзя использовать в качестве индексного регистра. - person David X; 29.06.2015

Арифметические инструкции, такие как add, sub, inc, dec, sar, sal, а также побитовые операции, такие как test, shl, shr, or, and, xor, neg и т. д., изменяют ZF.

person newgre    schedule 06.12.2011
comment
Спасибо за полный список, пригодится. Вы получили это из конкретной ссылки или знали об этом не понаслышке? - person Robert; 07.12.2011
comment
Я знал эти инструкции, но мне пришлось искать конкретные эффекты в руководствах Intel / Google. Я не знаю списка инструкций, затрагивающих ZF. - person newgre; 07.12.2011

математические операции, такие как inc и dec, также могут устанавливать нулевой флаг.

person John Knoeller    schedule 06.12.2011

Или, для начала, сохраните [push] флаги в стеке, [pop] получите стек в регистре, используйте арифметику или оператор с нужным битом в регистре, поместите регистр и вставьте флаг.

что-то вроде этого.

pushf
pop ax
or ax, 0x100 [this will set trap flag, you can get the value for any flag or flags you want]
push ax
popf
person A-Cube    schedule 25.02.2012