Come faccio a passare i parametri in assembler x86 chiamata di funzione

Occhiata a questo codice assembler. È stato progettato per la versione a 32 bit x86 e verrà compilato da nasm

   ...
   my_function:
        pop %eax
        ...
        ret


   main:
       push 0x08
       call my_function

Ho imparato molto tempo fa che possiamo utilizzare lo stack per il passaggio di parametri tra programma e funzioni.
Mi aspetterei che eax contiene 0x08, ma questo è falso, e non mi spiego perché.
Come devo fare per recuperare i miei parametri di una funzione ?

Guarda il suo altro risposta. Il problema è che la CHIAMATA si mette l’indirizzo di ritorno sullo stack, e che è ciò che si trova in EAX con il tuo codice.

OriginaleL’autore Bob5421 | 2016-06-22

One Reply
  1. 7

    In primo luogo, se si sta cercando di interfaccia con le altre lingue o librerie della piattaforma di lavoro, assicuratevi di leggere l’interfaccia definita per quella piattaforma. Ci sono una varietà di chiamata meccanismi che possono essere utilizzati.

    Nel tuo caso, il call istruzione sta spingendo l’indirizzo di ritorno sullo stack. Puoi accedere al tuo parametro utilizzando alcuni aritmetica e esp. Io assumo codice a 32 bit (32 bit stack di larghezza), dal momento che si sta utilizzando eax. Sto utilizzando la sintassi intel dal momento che non posso scrivere che senza guardare nulla:

    my_function:
        mov eax, [esp+4]    ; Move the contents of ESP+4 into EAX
                            ; ESP should be pointing at the 32 bit RIP.
                            ; ESP+4 should be the pushed parameter.
        ...
        ret
    
    
    main:
       push 0x08
       call my_function
    

    Nei tuoi commenti si chiede, per quanto riguarda questa risposta, se questo rappresenta una perdita di memoria. La risposta è “No”. Il motivo è che il chiamante è responsabile per pulire tutto ciò che si aggiunge alla pila. Un esempio più completo basato su gli altri commenti che sono stati scritti, potrebbe assomigliare a questo:

    my_function:
        push ebp            ; Store the current stack frame
        mov  ebp, esp       ; Preserve ESP into EBP for argument references
        and  esp, 0xfffffff0; Align the stack to allow library calls
        mov  eax, [ebp+8]   ; Move the contents of EBP+4 into EAX
                            ; EBP should be pointing at the 32 bit RIP.
                            ; EBP+4 should be the pushed parameter.
        ...                 ; Do lots of cool stuff
        mov  esp, ebp       ; Restore the stack and ebp
        pop  ebp
        ret
    
    
    main:
       push 0x08
       call my_function
       pop ebx              ; Clean up the stack
    

    Notare che quando abbiamo allineare la risma (se non siete sicuri perché questo sta accadendo, potrete trovare rapidamente quando si ricerca la chiamata standard per la piattaforma) a 16 byte limite, non ci prova nemmeno a capire quanto esp è cambiato. Dal ebp agirà come un “segnalibro” per noi, siamo in grado di lasciare esp spostare per allineamento o forse locale di allocazione della variabile senza altro pensiero.

    In funzione di epilogo si sposta ebp di nuovo in esp, che ripristina esp al suo valore originale quando è stata chiamata la funzione, quindi la pulizia di eventuali locali di allocazione e di allineamento delle operazioni che sono successe. Infine, abbiamo pop ebp fuori della pila, lasciando il ritorno puntatore il valore finale sullo stack all’interno della funzione. Ora ci ritorno.

    Dopo il ritorno abbiamo pulito con un pop.

    In alternativa, è possibile ripulire lo stack con un ritorno specificando il numero di byte per liberare sullo stack. Tutto dipende dal fatto che la vostra vocazione specifica chiamante di pulizia o chiamato la pulizia.

    Grazie Davide, ma nel tuo caso non è mai chiamata pop. Don t si pensa che è una perdita di memoria?
    Di solito è fino al chiamante (dopo call my_function) per fare il pop. Questo è solo il più breve esempio di come accedere allo stack parametro nella funzione all’interno, non è un esempio completo. Quindi sì, sarebbe “perdita”.
    Devo smontare alcuni eseguibili elf. A volte vedo che cambiare il valore di esp direttamente. Suppongo sia la stessa cosa che pop/push (tranne che non recupero o aggiungere valore). Vedo anche ebp. Suppongo che il reale indirizzo di memoria per lo stack éléments a ebp+esp ?
    L’ESP è cambiato direttamente per allocare lo spazio sullo stack. EBP è di solito utilizzato per tenere traccia originale EBP valore quando la funzione viene chiamata, in modo che la pila può essere pulito facilmente. Il valore di EBP è in genere memorizzati nello stack come parte della funzione preambolo, in condizioni normali di impiego, si dovrebbe aspettare di vedere le cose in pila a +8. A questo punto hai descritto un tipico “stack frame.” La cosa più importante per voi sapere, però, è che le cose che passano sullo stack è non tipico. In questi giorni, la maggior parte delle interfacce preferiscono fare uso di registri, che è più veloce, dato che non spinge e pop…
    …richiesti. Questo è il motivo per cui mi consiglia di cercare la chiamata standard per la piattaforma su cui si dovrà lavorare!

    OriginaleL’autore David Hoelzer

Lascia un commento