Dodam jeszcze jedną odpowiedź, aby odnieść się do niektórych tangencjalnych dyskusji, które miały miejsce.
C ABI (interfejs binarny aplikacji) pierwotnie wywoływany do przekazywania argumentów na stosie w odwrotnej kolejności (tj. - wypychany od prawej do lewej), gdzie wywołujący również zwalnia pamięć stosu. Współczesny ABI faktycznie używa rejestrów do przekazywania argumentów, ale wiele z zagadnień związanych z zniekształcaniem wraca do tego oryginalnego przekazywania argumentów stosu.
W przeciwieństwie do tego oryginalny Pascal ABI przesuwał argumenty od lewej do prawej, a wywoływany musiał przełamać argumenty. Oryginalny C ABI jest lepszy od oryginalnego Pascala ABI w dwóch ważnych punktach. Kolejność wypychania argumentów oznacza, że przesunięcie stosu pierwszego argumentu jest zawsze znane, co pozwala funkcjom, które mają nieznaną liczbę argumentów, gdzie wczesne argumenty kontrolują liczbę innych argumentów (ala printf
).
Drugim sposobem przewodzenia C ABI jest zachowanie w przypadku, gdy dzwoniący i wywoływany nie zgadzają się co do liczby argumentów. W przypadku C, o ile nie masz dostępu do argumentów poza ostatnim, nic złego się nie dzieje. W Pascalu niewłaściwa liczba argumentów jest usuwana ze stosu i cały stos jest uszkodzony.
Oryginalny system Windows 3.1 ABI był oparty na Pascalu. Jako taki, używał Pascal ABI (argumenty w kolejności od lewej do prawej, callee pops). Ponieważ każda niezgodność w liczbie argumentów może prowadzić do uszkodzenia stosu, powstał schemat zniekształcenia. Każda nazwa funkcji została zniekształcona liczbą wskazującą rozmiar w bajtach jej argumentów. Tak więc na komputerze 16-bitowym następująca funkcja (składnia C):
int function(int a)
Został zniekształcony function@2
, ponieważint
ma dwa bajty. Zrobiono to tak, że jeśli deklaracja i definicja są niezgodne, konsolidator nie znajdzie funkcji, a nie uszkodzi stosu w czasie wykonywania. I odwrotnie, jeśli program łączy się, możesz być pewien, że poprawna liczba bajtów jest pobierana ze stosu na końcu wywołania.
32-bitowy system Windows i nowsze wersje używają rozszerzenia stdcall
zamiast tego ABI. Jest podobny do Pascala ABI, z wyjątkiem tego, że kolejność push jest podobna do C, od prawej do lewej. Podobnie jak w przypadku Pascala ABI, zniekształcanie nazwy zmienia rozmiar bajtów argumentów na nazwę funkcji, aby uniknąć uszkodzenia stosu.
W przeciwieństwie do oświadczeń przedstawionych w innym miejscu tutaj, C ABI nie zmienia nazw funkcji, nawet w programie Visual Studio. I odwrotnie, funkcje zniekształcające udekorowane stdcall
specyfikacją ABI nie są unikalne dla VS. GCC obsługuje również ten ABI, nawet podczas kompilacji dla Linuksa. Jest to szeroko używane przez Wine , który używa własnego modułu ładującego, aby umożliwić łączenie w czasie wykonywania skompilowanych plików binarnych Linuksa ze skompilowanymi bibliotekami DLL systemu Windows.