Когда-то в молодости я увлекался асмом и с тех пор был свято уверен, что на x86 для повтора некоторых действий N ра нет ничего лучше цикла, в котором счетчик уменьшается от N до 0. Сейчас ради прикола попробовал такой «код» скомпилировать:
#include <stdio.h>
int main()
{
unsigned i;
for (i=0; i<100; i++) printf("Hello, world!\n");
return 0;
}
gcc -O4 -S test.c, а там (выравнивание поскипано)
xorl %ebx, %ebx
.L2:
movl $.LC0, %edi
addl $1, %ebx
call puts
cmpl $100, %ebx
jne .L2
Тогда я попробовал
#include <stdio.h>
int main()
{
unsigned i = 100;
do {
printf ("Hello, world!\n");
} while (--i);
}
Результат получился точно такой же. И только с -Os я получил свой decl %ebx; jne .L2
Собственно, вопрос: почему добавление единички у нас лучше, чем инкремент (это же как минимум длиннее)? И почему второй цикл был «перевернут»? Ведь декремент установит ZF и необходимость в сравнении просто отпадет сама собой.
P. S. Выставил -Os в make.conf, планирую пересобирать мир.