Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Al het geheugen buiten het huidige adres van RSP wordt beschouwd als vluchtig: het besturingssysteem of een foutopsporingsprogramma kan dit geheugen overschrijven tijdens een foutopsporingssessie van een gebruiker of een interrupt-handler. RSP moet dus altijd worden ingesteld voordat u probeert waarden te lezen of te schrijven naar een stackframe.
In deze sectie wordt de toewijzing van stackruimte voor lokale variabelen en de alloca-intrinsic beschreven.
Stacktoewijzing
Het prolog van een functie is verantwoordelijk voor het toewijzen van stackruimte voor lokale variabelen, opgeslagen registers, stackparameters en registerparameters.
Het parametergebied bevindt zich altijd onder aan de stack (zelfs als alloca dit wordt gebruikt), zodat het altijd grenzend is aan het adres van de afzender tijdens een functieoproep. Het bevat ten minste vier vermeldingen, maar altijd voldoende ruimte voor alle parameters die nodig zijn voor elke functie die kan worden aangeroepen. Houd er rekening mee dat er altijd ruimte wordt gereserveerd voor de registerparameters, zelfs als de parameters zelf niet naar de stack worden verplaatst; de aangeroepene is gegarandeerd van toegewezen ruimte voor alle parameters. Beginadressen zijn vereist voor de registerargumenten, zodat er een aaneengesloten gebied beschikbaar is als de aangeroepen functie het adres van de lijst met argumenten (va_list) of een afzonderlijk argument moet overnemen. Dit gebied biedt ook een handige plaats om registerargumenten op te slaan tijdens het uitvoeren van thunk en als foutopsporingsoptie (het maakt de argumenten bijvoorbeeld gemakkelijk te vinden tijdens foutopsporing als ze op hun thuisadressen in de prolog-code worden opgeslagen). Zelfs als de aangeroepen functie minder dan 4 parameters heeft, zijn deze vier stacklocaties in feite eigendom van de aangeroepen functie en kunnen deze worden gebruikt door de aangeroepen functie voor andere doeleinden, naast het opslaan van parameterregisterwaarden. De aanroeper mag dus geen informatie opslaan in dit stackgebied bij een functie-aanroep.
Als er dynamisch ruimte wordt toegewezen (alloca) in een functie, moet een niet-vluchtig register worden gebruikt als frame pointer om de basis van het vaste deel van de stack te markeren en dat register moet worden opgeslagen en geïnitialiseerd in de proloog. Wanneer alloca wordt gebruikt, kunnen oproepen naar dezelfde ontvanger van dezelfde afzender verschillende startadressen hebben voor hun registerparameters.
De stack wordt altijd 16-byte uitgelijnd, behalve in de proloog (bijvoorbeeld nadat het retouradres is gepusht), en behalve zoals aangegeven in Functietypen voor een bepaalde klasse van framefuncties.
Hier volgt een voorbeeld van de stack-indeling waarbij functie A een niet-leaf functie B aanroept. Het prolog van functie A heeft al ruimte toegewezen voor alle register- en stackparameters die door B aan de onderkant van de stack zijn vereist. De aanroep plaatst het retouradres en het proloog van B wijst ruimte toe voor de lokale variabelen, niet-vluchtige registers en de ruimte die nodig is om functies aan te roepen. Als B alloca gebruikt, wordt de ruimte toegewezen tussen het lokale variabele/niet-vluchtige registeropslaggebied en het parameterstackgebied.
Wanneer de functie B een andere functie aanroept, wordt het retouradres net onder het huisadres voor RCX gepusht.
Constructie van dynamisch parameterstack-gebied
Als er een framepointer wordt gebruikt, bestaat de optie om het parameterstackgebied dynamisch te maken. Dit wordt momenteel niet gedaan in de x64-compiler.
Functietypen
Er zijn in feite twee soorten functies. Een functie waarvoor een stackframe is vereist, wordt een framefunctie genoemd. Een functie waarvoor geen stackframe is vereist, wordt een leaf-functie genoemd.
Een framefunctie is een functie die stackruimte toewijst, andere functies aanroept, niet-compatibele registers opslaat of uitzonderingsafhandeling gebruikt. Er is ook een vermelding in de functietabel vereist. Een framefunctie vereist een prolog en een epilog. Een framefunctie kan dynamisch stackruimte toewijzen en een framepointer gebruiken. Een framefunctie beschikt over alle mogelijkheden van deze aanroepstandaard.
Als een framefunctie geen andere functie aanroept, is het niet vereist om de stack uit te lijnen (waarnaar wordt verwezen in sectiestacktoewijzing).
Een leaf-functie is een functie waarvoor geen functietabelvermelding is vereist. Het kan geen wijzigingen aanbrengen in niet-compatibele registers, inclusief RSP, wat betekent dat er geen functies kunnen worden aangeroepen of stackruimte kan worden toegewezen. Het is toegestaan om de stack niet uitgelijnd te laten terwijl deze wordt uitgevoerd.
malloc-uitlijning
malloc retourneert gegarandeerd geheugen dat geschikt is voor het opslaan van objecten die een fundamentele uitlijning hebben en die passen in de hoeveelheid toegewezen geheugen. Een fundamentele uitlijning is een uitlijning die kleiner is dan of gelijk is aan de grootste uitlijning die wordt ondersteund door de implementatie zonder een uitlijningsspecificatie. (In Microsoft C++ is dit de uitlijning die is vereist voor een doubleof 8 bytes. In code die is gericht op 64-bits platforms, is dit 16 bytes.) Een toewijzing van vier bytes wordt bijvoorbeeld uitgelijnd op een grens die ondersteuning biedt voor vier bytes of kleiner object.
Visual C++ staat typen toe die uitgebreide uitlijning hebben, ook wel overgelijnde typen genoemd. De SSE-typen __m128 en __m256typen die worden gedeclareerd met behulp van __declspec(align( n )) waar n groter is dan 8, hebben bijvoorbeeld uitgebreide uitlijning. Geheugenuitlijning op een grens die geschikt is voor een object waarvoor uitgebreide uitlijning is vereist, wordt niet gegarandeerd door malloc. Als u geheugen wilt toewijzen voor overgelijnde typen, gebruikt u _aligned_malloc en gerelateerde functies.
alloca
_alloca moet 16 byte zijn uitgelijnd, en is daarnaast verplicht om een framepointer te gebruiken.
De toegewezen stack moet ruimte erna opnemen voor parameters van vervolgens aangeroepen functies, zoals besproken in Stack Allocation.