Hola, aca voy a explicar las “calling conventions”, toda la informacion la voy a sacar de:
http://en.wikipedia.org/wiki/X86_calling_conventions
(esta en inglés)
-He notado que algunas especificaciones estan.. incompletas, quisa le falta decir como retorna o si se ponen de derecha a izqueirda o de izquierda a derecha los argumentos, yo solo saque la informacion de la pagina citada arriba de todo
-Cuando aveces digo que en C se puede indicar de que forma compilar la funcion, quisa no sea igual para todos los compiladores, hasta es probable que en algunos compiladores se pueda incluir otras calling conventions.
que son las calling conventions?
resulta que hace tiempo, con las maquinas de Unix, todo funcionaba como reloj, las funciones se llebaba bien entre ellas, pero parecio IBM, con sus pcs con procesador intel, sistema operativo de microsoft y hardware IBM, entonces tubieron que hacer una serie de reglas para que las funciones funcionen bien. estas reglas son las calling conventions.
que dicen estas reglas?
definen como se pasan los argumentos y como debe retornar un valor la función, por ejemplo, los argumentos se pueden pasar a los registros o a la pila, empezando por la derecha o por la izquierda.
sirve para cualquier lenguaje?
si, aunque en pocos lenguajes se puede especificar que reglas seguir, o bien, crear tus propias reglas (con asm, aunque tambien podes seguir las calling conventios ya establecidas obiamente)
creo que es importante para asm, pero no es de importancia cuando no podes especificar nada, pero saber que hace el compilador con tus funciones no esta de mas 
Las calling conventions se dividen en 2 grandes grupos
“caller clean-up”
“callee clean-up”
Caller clean-up:
Aca el que llame a la funcion se encarga de limpiar la pila (ya veremos que es eso), facilidad para las funciones con indefinida cantidad de argumentos, como lo es printf en C.
tenemos 3 “reglas”:
cdecl
syscall
optlink
cdecl:
la cdecl calling convention es la mas usada por compiladores de C
los argumentos (parametros) de la funcion son pasados por la pila, empezando de la derecha y terminando con el argumento de la izqueirda.
la funcion retorna el valor en el registro EAX, exepto para valores reales que se ponen en ST0.
los registros EAX, ECX y EDX quedan libres para la funcion (osea, los podes modificar tranquilamente)
en C para especificar que la funcion utilize este metodo debemos poner _cdecl antes del nombre de la funcion:
int _cdecl funcion(int, int, int);
un ejemplo:
int function_name(int, int, int);
int a, b, c, x;
...
x = function_name(a, b, c);
al compilarse queda:
push c
push b
push a
call function_name
add esp, 12 ;Limpia la pila
mov x, eax
el que llamo a la funcion debe limpiar la pila despues de la llamada, esto se hace regresando la pila a donde estaba, como tenemos 3 variables de 4 bytes, el valor de esp va a disminuir 12 bytes (los 3 push), asique para que vuelva a donde estaba hay que sumarle 12 a esp 
en caso de que el valor a retornar sea de 64 bits entonces retoran en EAX:EDX (32bits mas significativos en EAX y los menos significativos en EDX)
en Linux los puntos flotantes de 32 bits o los de 64 bits son pasados asi:
sub esp,8; hace espacio en la pila
fld [ebp+x]; carga el flotante de 64bits
fstp [esp]; pone el flotante de 64bits en la pila
call func;
add esp,8;
syscall:
Este es parecido a cdecl en que los argumentos se pasan de derecha a izqueirda.
EAX, EDX y ECX no se conservan. (creo que quiere decir que no los podemos modificar)
El tamaño de la lista de parametros se pasa a AL
Syscall es el metodo estandar para OS/2 32bits
optlink:
Los argumentos son puestos de derecha a izquierda. Los tres primeros (de la izquierda) se pasan por EAX, EDX y ECX, y hasta 4 variables flotantes se pasan de ST(0) a ST(3) aunque se reserva espacio en la pila para ellos.
en este caso EBP, EBX, ESI, y EDI son conservadas
se retorna por EAX o ST(0)
optlink se usa por los compiladores IBM VisualAge.
Callee clean-up:
cuando la funcion llamada limpia la pila, el compilador tiene que saber cuantos bytes debe “limpiar” en el tiempo de ejecucion, por eso este metodo no es compatible con funciones con la cantidad de argumentos variables (como printf).
este metodo es un poco mas eficiente.
la instruccion ret del x86 permite un un parametro de un byte que especifica el numero de posiciones de la pila a limpar antes de retornar.
ret 12
tenemos las sigientes:
pascal
register
stdcall
fastcall
Microsoft fastcall
Borland fastcall
Watcom register based calling convention
TopSpeed / Clarion / JPI
safecall
pascal
los parametros son pasados de izquierda a derecha (al contrario de cdecl)
retorna como cdecl
este metodo fue usado comunmente en 16 bit APIs OS/2 1.x , Microsoft Windows 3.x, y Borland Delphi version 1.x.
register
asi se lo llamaba a Borland fastcall.
stdcall
se pasan los argumentos de dercha a izqueirda
EAX, ECX y EDX son destinados para la funcion
y se retorna en EAX
este metodo es el estandar para WIN32
en C para indicar que use este metodo usamos
_stdcall
char _stdcall mifunc(int x);
fastcall
esta convencion no se estandarizó (creo que se escribe asi xD) por lo que cada compilador lo interpreta a su manera:
Microsoft fastcall
Microsoft o GCC __fastcall pasa los primeros 2 argumentos (de izquierda a derecha) en ECX y en EDX, el resto se ponen en la pila de DERECHA a izquierda.
Borland fastcall
Pasa de izquierda a derecha los argumentos en EAX, EDX y ECX, el resto por la pila (tambien de izquierda a derecha)
es el metodo estandard de Borland Delphi.
Watcom register based calling convention
Watcom no soporta la palabra clave __fastcall, exepto que se le haga un alias a NULL
el “registrer calling convention” se selecciona por la linea de comandos
los argumentos se pasan de izquierda a derecha por eax, edx, ebx, ecx. Si algun argumento no puede ser pasado por el registro, ese y todos los siguientes se pasan por la pila, los argumentos de la pila se pasan de DERECHA a izquierda
Watcom C/C++ admite “#pragma aux” que te permite definir tu propio metodo (no se como xD da un enlaze a http://www.openwatcom.org/index.php/Calling_Conventions#Specifying_Calling_Conventions_the_Watcom_Way pero eso no entraria en este post)
TopSpeed / Clarion / JPI
Los primeros 4 son pasados por eax, ebx, ecx y edx, para los puntos flotantes usamos st0, st1, st2, st3, st4, st5 y st6. parametros de estructuras son siempre pasados por la pila y cuando se acaban los registros usamos la pila
enteros se retornan por EAX
punteros por EDX
puntos flotantes por st0
safecall
En borland delphi este metodo se usa para chequekar errores, los errores se reportan cuando se retorna, y delphi automaticamente chekea ese valor devuelto y si es necesario manda algun mensaje de error.
safecall es igual a stdcall exepto que los errores son pasados por EAX (en vez de fs:[0]) mientras que el valor devuelto se pasa por la pila como si fuese un ultimo parametro out.
esta convencion va a perecer como cualquier otra convencion, aunque los errores son pasados por EAX, estos son automaticamente convertidos a la exprecion adecuada por el que llama a la funcion safecall.
estas 2 declaraciones son iguales:
function function_name(a: DWORD): DWORD; safecall;
function function_name(a: DWORD; out Result: DWORD): HResult; stdcall;
thiscall
esta tiene 2 verciones, caller-clean up y callee-clean up, depende del compilador
para el GCC, thiscall es igual que cdecl, la diferencia es que agrega “this pointer”, que se pone ultimo en la pila, como si fuese el primer parametro de la funcion
para microsoft visual C++ “this pointer” es pasado por ECX y la funcion llamada es la que limpia la pila, exepto para las funciones con numeros variados de parametros que es la funcion que llama la que limpia.
thiscall puede ser esplicitamente especificado en Microsoft Visual C++ 2005 y mayores. para cualquier otro compilador thiscall no es una palabra reservada
(no se que es a lo que se refiere con “this pointer”
The difference is the addition of the this pointer, which is pushed onto the stack last, as if it were the first parameter in the function prototype.
)
Intel ABI
esta convencion muchos compiladores y lenguajes usan, segun Intel ABI, EAX, EDX y ECX son de uso libre para la funcion, asique no tienen que ser preservadas.
Microsoft x64 calling convention
esta convencion, como bien deben de suponer, es para arquitecturas de 64 bits, y utiliza las ventajas de los 64 bits utilizando RCX, RDX, R8 y R9 para enteros y punteros
XMM0, XMM1, XMM2, XMM3 para flotantes, el resto se pone en la pila y se retorna por RAX.
cuando compilamos en 64bits utilizando las herramientas de microsoft, hay una sola convencion (esta xD) asique stdcall cdecl ,fastcall etc son todas una y la misma
es de la responsabilidad del que llama a la funcion reservar 32bytes (sin importar el numero de parametros) en la pila antes de llamar a la funcion, este espacio es para RCX, RDX, R8 y R8
AMD64 ABI convention
este sistema es usado en linux (obiamente 64 bits xD) y otros sistemas operativos menos los de microsoft
RDI, RSI, RDX, RCX, R8 y R9 son usados para enteros y punteros
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6 y XMM7 para flotantes
los demas son por la pila y se retorna en RAX.
Standard exit and entry sequences for C code
asi es como EMPIEZA la funcion
_function:
push ebp ;guarda el ebp viejo
mov ebp, esp ;ahora la base de la pila es el puntero a la pila
;arriba de todo esta el viejo ebp y seguida por la posicion de retorno
sub esp, x ;x es el tamaño de todas las variables "automatic" ("automatic" es algo de C, por defecto todas son automatic)
lo unico que explico es que sub esp, x es hacer espacio, donde dentro van a estar las variables locales automaticas.
este comportamiento hace posible hacer funciones recursivas
y asi es como TERMINA
mov esp, ebp ;reset the stack to "clean" away the local variables
pop ebp ;restore the original base pointer
ret ;return from the function
creo que esta claro, un ejemplo de este code en C:
int _cdecl MyFunction(int i){
int k;
return i + k;
}
produce
;entry sequence
push ebp
mov ebp, esp
sub esp, 4 ;create function stack frame
;function code
mov eax, [ebp + 8]
;move parameter i to accumulator
add eax, [ebp - 4]
;add k to i
;result is returned in eax
;exit sequence
mov esp, ebp
pop ebp
ret
aunque esto algunos compiladores lo optimizan cuando no necesitan hacer espacio en la pila y esas cosas.
si.. es un poco largo y pesado, no creo que se lo lean todo xD quisa tienen duda y consultan aca
salu2! y espero que les haya gustado!