- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
program Project1;
Var
i,j : Integer;
begin
i := 300001; j := 300002;
asm
MOV EAX, I;
XCHG EAX,j
MOV I, EAX;
end;
Write(i,' ',j); Readln;
end.
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+90
program Project1;
Var
i,j : Integer;
begin
i := 300001; j := 300002;
asm
MOV EAX, I;
XCHG EAX,j
MOV I, EAX;
end;
Write(i,' ',j); Readln;
end.
Ещё один кулхацкерный метод перестановки значений двух чисел местами.
tirinox 30.12.2012 02:02 # +7
bormand 30.12.2012 10:35 # +5
LispGovno 30.12.2012 12:47 # −4
Компилятор заменит XCHG EAX,j как-то так:
Соответственно весь код ,будет выглядеть примерно как:
bormand 30.12.2012 13:42 # +5
Компилятор не будет ничего заменять. Раз уж программист написал в асмовставке xchg - значит так тому и быть. Если я не прав - пруфлинк в студию.
А если не выябываться с асмовставками, и написать tmp=x; x=y; y=tmp;, то при удачных обстоятельствах (к примеру свопают 2 локальных переменных и не в цикле), то компилятор вообще избавится от этого шлака, и вообще не будет генерить для него асм. А в самом неудачном случае да, получится твой нижний код.
wissenstein 30.12.2012 15:38 # 0
Обоснуйте!
bormand 30.12.2012 15:54 # +1
Как выше правильно заметил LispGovno, xchg имеет неявный lock префикс, в случаях, если одним из операндов является память. If a memory operand is referenced, the processor’s locking protocol is automatically implemented for the duration of the exchange operation, regardless of the presence or absence of the LOCK prefix or of the value of the IOPL. (IA-32 Intel Architecture, том 2) Поэтому компилятор не имеет права поменять xchg eax, j в асмовставке на mov ebx, j; mov j, eax; mov eax, ebx.
Да и вообще - зачем компилятору менять содержимое асмовставки? В конце концов программист ее не от хорошей жизни писал.
wissenstein 30.12.2012 16:11 # +1
То я высказывался по поводу требований пруфлинка от возражателей. Ведь доказывать должен тот, кто утверждает, а не тот, кто отрицает (Дигесты и Кодекс Юстиниана, книга 22, титул 3, правило 2, http://www.e-reading.org.ua/chapter.php/21741/258/Dushenko_-_Mysli_i_izrecheniya_drevnih_s_ukazaniem _istochnika.html)
bormand 30.12.2012 16:19 # 0
Так что правило "Ведь доказывать должен тот, кто утверждает, а не тот, кто отрицает" я не нарушал :P
wissenstein 30.12.2012 16:20 # 0
anonimb84a2f6fd141 30.12.2012 20:15 # 0
bormand 30.12.2012 20:52 # +1
Да, точно так же, как он избавляется от ненужных переменных, временных переменных, присваиваний одной и той же переменной два раза подряд и т.п.
На этом этапе компилятор еще не задумывается о ячейках памяти и регистрах. Лучше всего представить это как набор виртуальных регистров, по одному на каждый промежуточный результат. Причем если результат протащили через 30 переменных, он все равно останется в одном виртуальном регистре.
А вот ближе к концу компиляции он займется распределением настоящих регистров, и выделением ячеек в стеке под те виртуальные регистры, которые не помещаются в физические. Несколько виртуальных регистров могут попасть в одну ячейку стека или один и тот же регистр, если, конечно, они не требуются одновременно.
Поэтому у качественного оптимизирующего компилятора переменные в стеке и регистры имеют мало общего с переменными в исходном коде...
P.S. swap с кучей и глобальными переменными ему так искоренить не удастся, лучше всего оптимизируются именно локальные переменные.
anonimb84a2f6fd141 30.12.2012 21:36 # 0
Я понял. То есть переменные в коде - это смысловое разграничение данных, а результирующее разграничение по памяти и регистрам - физическое, направленное на оптимальность.
Вы читали что-то по компиляторам, кроме документации к конктретным продуктам? Кнут вроде ещё не сваял свой томик. Дайте линков?
bormand 31.12.2012 09:44 # +1
В основном как раз документацию по LLVM и GCC, специализированных книг по компилерам не читал, т.к. свой пока писать не собираюсь...
bormand 30.12.2012 21:00 # +2
eth0 30.12.2012 21:33 # +2
bormand 30.12.2012 21:40 # 0
LispGovno 30.12.2012 23:30 # 0
Лол, как ты мои слова извратил, тролль. Я тебе сказал, как-бы поступил компилятор на месте программиста. Сказал, что он в целях оптимизации без нужды выставлять #LOCK не будет на строчку кеша или шину в многоядерной среде.
myaut 30.12.2012 13:38 # 0
bormand 30.12.2012 13:54 # +3
Реквестирую в тред Тараса.
Vindicar 30.12.2012 15:53 # 0
bormand 30.12.2012 16:04 # +3
Зачем компилятор генерит код, что-то держащий в регистрах? Да только ради эффективности, чтобы каждый раз не дергать их из оперативки.
В случае с асмовставкой ему придется от такой идеи отказаться (асмовставка может очень-очень косвенным путем потрогать и изменить переменную в стеке), и по-честному поместить переменную в стек, а после асмовставки, если ему вновь понадобится эта переменная, заново ее загрузить в регистр.
Имхо паскаль использует именно этот не самый эффективный, зато очень надежный способ (раз у него нет тонкой настройки попорченных регистров, как в gcc).
vladthesparrow 09.01.2013 17:03 # −2
bormand 09.01.2013 18:42 # +2
bormand 09.01.2013 19:08 # +1
bormand 09.01.2013 19:27 # +1
vistefan 09.01.2013 19:30 # +2
Ведь в ГК2.0 будет превью?
bormand 09.01.2013 19:30 # +1