2009-09-08 11 views

Respuesta

12

Para hacer eso, necesitarás crear un método "desnudo" con _declspec (desnudo) y escribirte el prólogo y el epílogo que normalmente crea el compilador.

El objetivo de un prólogo es:

  • estableció EBP y ESP
  • espacio
  • reserva en la pila para las variables locales
  • guardar registros que debe ser modificada en el cuerpo de la función

un epílogo tiene que:

  • restaurar el registro salvado valora
  • limpiar el espacio reservado para las variables locales

Aquí es un prólogo estándar

push  ebp    ; Save ebp 
mov   ebp, esp   ; Set stack frame pointer 
sub   esp, localbytes ; Allocate space for locals 
push  <registers>  ; Save registers 

y un epílogo estándar:

pop   <registers> ; Restore registers 
mov   esp, ebp  ; Restore stack pointer 
pop   ebp   ; Restore ebp 
ret      ; Return from function 

sus variables locales comenzará entonces en (ebp - 4) y bajará a (ebp - 4 - localbytes). Los parámetros de la función comenzarán en (ebp + 8) y irán hacia arriba.

3

Es imposible crear una variable C en ensamblador: el compilador de C tiene que saber acerca de la variable (es decir, su tipo y dirección), lo que significa que tiene que ser declarado en el código C.

Lo que se puede hacer es acceder a los símbolos definidos en el ensamblador mediante declaraciones extern en C. Esto no funcionará para las variables con duración de almacenamiento automático, ya que no tienen una dirección fija pero están referenciadas con respecto a la base puntero.

Si no desea acceder a las variables fuera del bloque asm, puede usar la pila para almacenar datos de ensamblador local. Hemos de tener en cuenta que tiene que restaurar el puntero de pila a su valor anterior a la salida del bloque de asm, por ejemplo

sub esp, 12  ; space for 3 asm-local 32bit vars 
mov [esp-8], 42 ; set value of local var 
[...] 
push 0xdeadbeaf ; use stack 
[...]    ; !!! 42 resides now in [esp-12] !!! 
add esp, 16  ; restore esp 

Si no desea que las direcciones relativas de las variables locales que cambiar cada vez que se manipula la pila (es decir, use push o pop), debe establecer un marco de pila (es decir, guardar la base de la pila en ebp y direcciones locales en relación con este valor) como se describe en cedrou's answer.

+0

¿está seguro de sub esp, 3 dará espacio para 3 de 32 bits vars? Tenía la idea de que para cada var de 32 bits tendría que tomar 4 de esp. –

+0

Al menos C++ lo define internamente de la siguiente manera: var_4 = dword ptr -4 –

+0

tiene razón, no debería responder preguntas tan tarde por la noche;) – Christoph

3

Las variables locales son asignados y liberados mediante la manipulación del espacio disponible en la pila de llamadas a través del registro ESP, es decir:

__asm 
{ 
    add esp, 4 
    mov [esp], 2; 
    ... 
    sub esp, 4 
} 

En general, esto es mejor manejado por el establecimiento de un "marco de pila" de la función de llamada en su lugar y, a continuación, acceder a las variables locales y parámetros de función() usando compensaciones dentro del marco, en lugar de utilizar el registro ESP directamente, es decir:

__asm 
{ 
    push ebp 
    mov ebp, esp 
    add esp, 4 
    ... 
    mov [ebp-4], 2; 
    ... 
    mov esp, ebp 
    pop ebp 
} 
Cuestiones relacionadas