2009-05-15 16 views
3

Когда я прочитал this вопрос Я вспомнил, как кто-то однажды сказал мне (много лет назад), что с точки зрения ассемблера эти две операции очень разные:Разница между n = 0 и n = n - n

n = 0; 

n = n - n; 

Это правда, и если да, то почему это так?

EDIT: Как указано в некоторых ответах, я думаю, это было бы довольно легко для компилятора для оптимизации в одно и то же. Но то, что я нахожу интересным, - это то, почему они будут отличаться, если компилятор имеет совершенно общий подход.

+0

Потому что они не то же самое? –

+0

Вот о чем вопрос. Человек, рассказывающий мне об этом, сказал, что «под капотом» они будут производить разные машинные коды, а другой быстрее. К сожалению, я не помню полный аргумент. – sharkin

ответ

3

В первые дни, память и CPU циклы были скудны. Это приводит к большому количеству так называемых «оптимизаций пробок». Давайте посмотрим на код:

move.l #0, d0 

moveq.l #0, d0 

sub.l a0,a0 

Первая команда будет нужно два байта для оп-кода, а затем четыре байта для значения (0). Это означало, что четыре байта потрачены впустую, плюс вам потребуется дважды получить доступ к памяти (один раз для кода операции и один раз для данных). Sloooow.

moveq.l был лучше, так как он объединил данные в op-код, но только разрешил записывать значения между 0 и 7 в регистр. И вы были ограничены только регистрами данных, не было быстрого способа очистить адресный регистр. Вам придется очистить регистр данных, а затем загрузить регистр данных в адресный регистр (два op-кода. Bad).

Для перехода к последней операции, которая работает в любом регистре, требуется только два байта, одно чтение. В переводе на C, вы получите

n = n - n; 

, которая будет работать для наиболее часто используемых типов n (целое число или указатель).

+0

Вы говорите, что n = n-n вариант на самом деле является/более эффективным, чем n = 0? – sharkin

+0

Это будет, как правило, в случае, если номер уже находится в регистре – stephan

+0

Amazing. Это именно тот ответ, который я надеялся получить. – sharkin

4

Оптимизирующий компилятор будет выдавать один и тот же код сборки для двух.

4

Это может зависеть от того, объявлен ли n как volatile или нет.

+0

Правда, но я не могу придумать реальный случай, когда вы сделаете n volatile, а затем выполните n = n - n –

+1

Конечно, но я не могу придумать реальный случай, когда вы будете делать n = nn в первую очередь. – mouviciel

+0

Спасибо за ответ, но использование «volatile» для меня тоже очень «реально». Это всего лишь теоретический/гипотетический вопрос для образовательных целей. – sharkin

7

компилятор VC++ 6.0, без оптимизаций:

4:  n = 0; 
0040102F mov   dword ptr [ebp-4],0 
5: 
6:  n = n - n; 
00401036 mov   eax,dword ptr [ebp-4] 
00401039 sub   eax,dword ptr [ebp-4] 
0040103C mov   dword ptr [ebp-4],eax 
10

Написание кода на ассемблере часто используется:

xor eax, eax 

вместо

mov eax, 0 

Это потому, что с первого заявления у вас есть только код операции и не задействованный аргумент. Ваш процессор будет делать это в 1 цикле (вместо 2). Я думаю, что ваш случай - нечто похожее (хотя и с использованием sub).

+1

Да, вы могли бы сказать sub eax, eax. Единственное различие - это флаги, которые устанавливаются операцией. – 2009-05-15 09:52:15

+0

Вы не можете быть уверены в * циклах *. Причина в том, что на самом деле это не циклы, напрямую. xor eax, eax производит более короткую (3 байта: 6631C0) команду, чем mov eax, 0 (6 байт: 66B800000000) в архитектуре x86. sub eax, eax также создает 3-байтовую инструкцию. В то время как для современных процессоров нет большой разницы между sub и xor, xor требует гораздо более простой схемы и имеет потенциал быть более быстрым –

+0

абсолютно правильно, это все о неявных мнемонических параметрах и, следовательно, уменьшении размера инструкции. – none

2

Методика ассемблере обнуления регистра путем вычитания его из себя или XORing его с собой интересный один, но это не реально перевести на C.

Любой оптимизации C компилятор будет использовать этот метод если это имеет смысл, и попытка написать его явно не принесет ничего.

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