volatile
или нет, единственная техническая причина, по которой EAX
должна должна быть инициализирована непосредственно перед выполнением вызова функции в Windows, если объявлено function
__syscall
, то есть с использованием соглашения о вызовах Windows CS_SYSCALL. Концептуально это немного похоже на соглашение UN * X x86_64, где %al
содержит число аргументов типа с плавающей запятой, переданных в регистрах %xmm
.
Соглашение о вызове системного вызова в Windows идентично __cdecl
, то есть аргументы функции в стеке в обратном порядке, но с добавлением, что AL
содержит счетчик количества аргументов; это делается для того, чтобы код ядра, который обычно находится в конечном конце, знал, сколько данных нужно прочитать из пользовательского стека в стек ядра для получения аргументов.
EAX
- это рабочий регистр для всех соглашений о вызовах в 32-битной Windows, его значение никогда не сохраняется в вызовах функций, инициализация его непосредственно перед выполнением вызова является избыточной. Даже если переменная содержит volatile
, потому что простая перезагрузка не является барьером памяти и не "фиксирует" предыдущее хранилище. Кроме того, местоположение [EBP - 4]
находится в стеке , поэтому переменная local (а квалификатор volatile
не имеет особого смысла).
Если это не пропущенная оптимизация, то это может быть вызов __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);
}
Это может создать выходные данные сборки, как у вас.