volatile
czy nie, tylko techniczny powód EAX
byłoby muszą być inicjowane bezpośrednio przed nawiązaniem połączenia funkcji w systemie Windows były jeśli function
deklaruje __syscall
, czyli używając wzywającą konwencję Okna CS_SYSCALL. Koncepcyjnie jest to trochę podobne do konwencji UN * X x86_64, w której %al
zawiera liczbę argumentów typu zmiennopozycyjnego przekazanych w rejestrach %xmm
.
Konwencja wywoływania syscall w systemie Windows jest identyczna z __cdecl
, tj. Funkcja działa na stosie w odwrotnej kolejności, ale z dodatkiem, że AL
zawiera liczbę argumentów; robi się to tak, że kod jądra, który zwykle znajduje się na końcu tego, wie, ile danych należy odczytać z stosu użytkownika na stosie jądra, aby pobrać argumenty.
EAX
jest rejestrem zdrapek dla wszystkich konwencji wywoływania w 32-bitowych systemach Windows, jego wartość nigdy nie jest zachowywana przez wywołania funkcji, inicjowanie go bezpośrednio przed wykonaniem połączenia jest zbędne. Nawet jeśli zmienna, którą trzyma, to volatile
- ponieważ proste ponowne ładowanie nie jest barierą pamięci i nie "zatwierdza" poprzedniego sklepu. Ponadto lokalizacja [EBP - 4]
znajduje się w zakresie stosu, więc zmienna to lokalna (a kwalifikator volatile
ma niewielki sens).
Jeśli nie jest stracona optymalizacja może to być wezwanie z __syscall function(...)
z różną liczbą argumentów, takich jak hipotetycznie
__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);
}
ta mogłaby tworzyć montażowej jak twoje.
Widziałem kompilatory robiące głupsze rzeczy niż to ... – Mysticial
@Mysticial: Oh lol ... po raz pierwszy zauważyłem coś takiego. :) Dobrze wiedzieć. – Mehrdad
Być może w pierwszym pchnięciu jest gałąź. –