2013-11-20 14 views
6

Ho una funzione con la firma:Recuperare argomenti di una procedura di assemblaggio x64 MASM

extern "C" int foo(int a, int b, int c, int d, int e); 

che è in realtà scritto in assembly.

Con ml (32 bit), utilizzando convenzione di chiamata standard che si può tranquillamente scrivere

.code 
foo PROC a: DWORD, b: DWORD ,c: DWORD, d: DWORD, e: DWORD 

    mov eax, d 
    mov ebx, e 

e iniziare a utilizzare le etichette per accedere ai argomenti

Con ml64 (64 bit) la fastcall è il unica convenzione disponibile. Non ho problemi ad accedere primi argomenti memorizzati nei registri, ma problemi per accedere quelli nella pila (e in questo esempio): Ho provato

.code 
foo PROC a: DWORD, b: DWORD ,c: DWORD, d: DWORD, e: DWORD 

e

.code 
foo PROC e: DWORD 

ma il valore in e è spazzatura.

Ho scoperto che se utilizzo direttamente l'indirizzo di stack, trovo il valore.

.code 
foo PROC e: DWORD 

    mov eax, r9     ; d 
    mov ebx, DWORD PTR[rbp + 48] ; e 

C'è un altro modo?

risposta

3

documentazione spiega tutto ... In Windows, i primi quattro parametri interi sono passati nei registri RCX, RDX, R8, R9 e in virgola mobile in XMM0, XMM1, XMM2, XMM3, qualcosa di più di quattro parametri vengono passati la pila sopra lo spazio d'ombra. Per i SO di tipo Unix è un po 'diverso.

Così, il vostro esempio è corretto - mov ebx, DWORD PTR[rbp + 48] ; e

spazio Ombra = 32 + salvati RBP = 40 + 5 ° parametro = 48

0

dato

extern "C" int foo(int a, int b, int c, int d, int e); 

ho scoperto che Visual Studio 2010 doesn salvare il puntatore di base RBP se

.code 
foo PROC 

ma salvare il puntatore base se

.code 
foo PROC e: DWORD 

Le versioni successive (vs2015) non consentono il secondo codice.

There is an optional optimization in x64 systems where RBP is not used (scoperto in modo difficile). Si dice:

L'uso convenzionale del% rbp come puntatore cornice per stack frame può essere evitato utilizzando% RSP (lo stack pointer) per indicizzare telaio stack.Questa tecnica salva due istruzioni nel prologo e l'epilogo e rende disponibile un registro generale per tutti gli usi (% rbp) .

quindi è possibile che o foo PROC e: DWORD pretende molto di compilazione (vs2015), o si blocca a causa foo PROC RBP è nullo.

Il modo corretto per recuperare argomenti stack è quello di utilizzare il puntatore RSP pila dato che

Dove num_saved_reg è il numero di registri specificate nella direttiva PROC. Quindi, quando rbp non viene salvato (altrimenti aggiungi 8)

PROC -> DWORD PTR[rsp + 40] 
PROC use RDI -> DWORD PTR[rsp + 40 + 8] 
PROC use RDI RSI RBX -> DWORD PTR[rsp + 40 + 24] 
Problemi correlati