2012-01-25 3 views
10

я демонтировал объектный файл (скорее всего сгенерированы с использованием компилятора Visual C++) с использованием DumpBin и увидел следующий фрагмент кода:Почему компилятор генерирует этот код?

...   ... 
mov   dword ptr [ebp-4],eax  // Why save EAX? 
push  dword ptr [ebp+14h] 
push  dword ptr [ebp+10h] 
push  dword ptr [ebp+0Ch] 
push  dword ptr [ebp+8] 
mov   eax,dword ptr [ebp-4]  // Why restore EAX? Did it change at all? 
call  <function> 
...   ... 

Может кто-то пожалуйста, объясните, почему регистр EAX в настоящее время сохраняются и восстанавливаются через эти 4 push инструкции?

+2

Я видел, как компиляторы делали что-то глупое, чем это ... – Mysticial

+0

@Mysticial: О, лол ... я впервые заметил что-то подобное. :) Хорошо знать. – Mehrdad

+7

Возможно, есть ветка в первый толчок. –

ответ

9

Кроме того, возможно, он скомпилирован в режиме выпуска, но эта переменная была отмечена как volatile, которая сообщает компилятору, что такая переменная может измениться без его ведома, поэтому она вынуждена постоянно записывать/восстанавливать ее в стеке/из стека

+0

Ahhhh это вполне возможно! +1 спасибо. – Mehrdad

+0

Я не уверен, что 'volatile' будет иметь значение здесь. 'volatile' относится к ячейке памяти, но EAX - это регистр; вы не можете пометить регистр как изменчивый. Поэтому 'volatile' объяснил бы, что [ebp-4] перезагружается * на * eax непосредственно перед каждой операцией, но не eax сохраняется. – Crashworks

+0

Для некоторой арифметики компилятор _has_ загружает ячейку памяти, помеченную в регистре, в переменную, поскольку операция не возможна в команде read-modify-write. После этого сегмента кода может появиться магазин, и до этого может начаться загрузка, поэтому из имеющейся информации это может быть абсолютно возможным. Но это не просто пропущенная оптимизация VC. – hirschhornsalz

6

Было ли это построено в режиме отладки? Если это так, компилятор хранит каждую локальную переменную в стеке, чтобы отладчик мог найти их согласованным образом.

Эквивалент таких ненужных запасов и перезагрузок является одной из оптимизаций, которые представляют собой режим «выпуска».

+0

Я считаю, что * предполагается, что это код режима релиза (нет «отладочной» версии чего-либо связанного я могу видеть где угодно ...), но я не уверен ... У меня нет исходного кода или. Но +1 это разумное предположение, спасибо. – Mehrdad

2

volatile или нет, только технической причины EAX бы должны быть инициализированы непосредственно перед выполнением вызова функции на Windows, были если function объявлен __syscall, т.е. используя соглашение о вызовах для Windows CS_SYSCALL. Понятно, что это немного похоже на соглашение UN * X x86_64, где %al содержит количество аргументов типа с плавающей запятой, прошедших в регистрах %xmm.

Конвенция о вызовах вызова вызова в ОС Windows идентична __cdecl, то есть функции args на стеке в обратном порядке, но с добавлением, что AL содержит счетчик количества аргументов; это делается так, что код ядра, который обычно находится на последнем конце, знает, сколько данных нужно считывать из стека пользователя в стек ядра для извлечения аргументов.

EAX является регистром царапин для всех соглашений о вызовах на 32-битной Windows, его значение никогда не сохраняется по функциональным вызовам, инициализируя его непосредственно перед выполнением вызова, является избыточным. Даже если переменная, которую она держит, равна volatile, потому что простая перезагрузка не является барьером памяти и не «фиксирует» предыдущий магазин. Кроме того, местоположение [EBP - 4] находится в стеке , поэтому переменная местная (и определитель практически не имеет смысла).

Если это не пропустил оптимизации, то это может быть отсылкой к __syscall function(...) с различным числом аргументов, как, гипотетически,

__syscall printf_syscall_conv(char *fmt, ...); 

void possibly_print_three_vals(char *fmt, int val1, int val2, int val3) 
{ 
    if (*strchr('%', fmt) == '\0') // if no "%" in fmt, pass no args 
     printf_syscall_conv(fmt); 
    else 
     printf_syscall_conv(fmt, val1, val2, val3); 
} 

Это, вероятно, может создать выход сборки, как ваша.

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