Benvenuto! Per postare e godere delle funzionalità del forum registrati, occorrono pochi secondi ed è gratis!

Piccolo Dubbio
(Questo messaggio è stato modificato l'ultima volta il: 28/10/2013, 2:25 da digger.)

Il criceto mannaro
Messaggi: 3,536
Discussioni: 201
Registrato: 03-2011
Mix: 3,737
la differenza è molto semplice, ma devi avere già chiaro in testa come funziona a livello assembly il passaggio di parametri nella chiamata a funzioni.

In generale, sia con chiamate stdcall che cdecl quando chiami una funzione e gli vuoi passare un parametro, quello che fai è "pushare" quel parametro sullo stack, quindi chiami la funzione, all'interno della funzione il parametro è ancora disponibile sullo stack e da li viene prelevato per svolgere i compiti della funzione.

La differenza tra i due consiste in CHI si deve preoccupare di sistemare lo stack dopo che finisce l'esecuzione della funzione e si ritorna al chiamante.

cdecl: è la funzione, all'interno del proprio codice, che si preoccupa di sistemare lo stack togliendo i parametri pushati dal chiamante prima dell'esecuzione della funzione

stdcall: è il chiamante che deve preoccuparsi di togliere dallo stack i parametri una volta tornati dalla funzione

Il modo migliore di vederlo comunque è se ti scrivi un piccolissimo programma in C dove nel main chiami 2 funzioni, una con cdecl e una con stdcall passando ad entrambe un parametro.
Poi vai a debuggare con OllyDbg il tuo programmino e allora vedi esattamente quello che sto dicendo.

Ad esempio:
    C++ Programming
  1. int _stdcall funz1(int val)
  2. {
  3. return (val*2);
  4. }
  5.  
  6. int _cdecl funz2(int val)
  7. {
  8. return (val*3);
  9. }
  10.  
  11. int main(int argc, char* argv[])
  12. {
  13. int res = funz1(10);
  14. int res2 = funz2(res);
  15. return res2;
  16. }



Se andiamo a vedere con Olly troviamo questo:

funz1 (cdecl):
    ASM Programming
  1. PUSH EBP
  2. MOV EBP,ESP
  3. MOV EAX,DWORD PTR SS:[ARG.1]
  4. SHL EAX,1
  5. POP EBP
  6. RETN 4 <--- la funz. ripulisce lo stack togliendo una DWORD, il parametro



funz2 (stdcall):
    ASM Programming
  1. PUSH EBP
  2. MOV EBP,ESP
  3. MOV EAX,DWORD PTR SS:[ARG.1]
  4. IMUL EAX,EAX,3
  5. POP EBP
  6. RETN <---- qui NON è la funzione a ripulire



E vediamo il codice nella funzione main, ovvero il chiamante:
(ho lasciato solo la parte che ci interessa)

chiamata a funz1 (cdecl)
    ASM Programming
  1. PUSH 0A <-- pushiamo il parametro sullo stack
  2. CALL funz1 <-- dentro la funzione pulisce lo stack



chiamata a funz2 (sdcall)
    ASM Programming
  1. PUSH EAX <-- pushiamo il parametro sullo stack
  2. CALL funz2 <-- la funzione dentro NON pulisce lo stack quindi...
  3. ADD ESP,4 <--- deve farlo il chiamante, togliendo una DWORD dallo stack



Finchè sei tu che chiami le tue funzioni nel tuo programma non ha molta imporanza che la chiamata sia cdecl (il default) o che sia stdcall.
L'importanza nasce nel momento in cui chiami funzioni che si trovano in altre librerie o comunque esterne al tuo programma.
Un esempio sono le API di windows, che solitamente usano la chiamata stdcall.
Il problema di chiamare una funzione con la convenzione sbagliata è di ottenere un crash sicuro perchè quello che succede è che lo stack viene corrotto.


digger
28/10/2013, 2:19
#2
Cerca


Messaggi in questa discussione
Piccolo Dubbio - da Cyanstack - 28/10/2013, 1:24
RE: Piccolo Dubbio - da digger - 28/10/2013, 2:19
RE: Piccolo Dubbio - da Cyanstack - 28/10/2013, 11:30
RE: Piccolo Dubbio - da digger - 29/10/2013, 0:25

Discussioni simili
Discussione Autore Risposte Letto Ultimo messaggio
  Dubbio float Cyanstack 4 1,802 20/11/2013, 12:58
Ultimo messaggio: Cyanstack



Utenti che stanno guardando questa discussione: 1 Ospite(i)