Pregunta

i cierto código (montaje en línea).

void NativeLoop()
{
    int m;
    __asm
    {
        PUSH ECX
        PUSH EDX
        MOV  ECX, 100000000
NEXTLOOP:
        MOV  EDX, ECX
        AND  EDX, 0X7FFFFFFF
        MOV  DWORD PTR m, EDX
        DEC  ECX
        JNZ  NEXTLOOP
        POP  EDX
        POP  ECX
    }
}

MS C ++ Automagicaly agrega estos códigos (marcados con **) a mi procedimiento.
¿Por qué?
cómo evitarlo?

  **push        ebp  
  **mov         ebp,esp 
  **push        ecx  
  push        ecx  
  push        edx  
  mov         ecx,5F5E100h 
NEXTLOOP:
  mov         edx,ecx 
  and         edx,7FFFFFFFh 
  mov         dword ptr m,edx 
  dec         ecx  
  jnz         NEXTLOOP
  pop         edx  
  pop         ecx  
  **mov         esp,ebp 
  **pop         ebp  
  **ret
¿Fue útil?

Solución

Es el código de entrada y salida estándar de la función. Se establece y derriba el marco de pila. Si no desea que se puede utilizar __declspec (desnuda). No se olvide de incluir el RET si lo hace.

Sin embargo, el fragmento se basa en un marco de pila válida, la variable "m" lo requiere. Está dirigido a [ebp-10]. Sin el preámbulo, el registro ebp no se establece correctamente y se le corromper el marco de pila de la persona que llama.

Otros consejos

Se mantiene la pila de llamadas. Si ha definido la función como

int NativeLoop() { }

Se podría ver el mismo conjunto.

Recuerdo que puede __declspec(naked) en MSVC ++, lo que significa que usted tiene que cuidar de la pila usted mismo, eso significa que debe guardar todos los registros que le daban un golpe, y restaurarlo.

No hay el uno en reglas para hacerlo correctamente, ya que depende de convención de llamada. Ver http://en.wikipedia.org/wiki/X86_calling_conventions .

Nota al margen: En gcc, explitly estado para el compilador lo que va a conducir válida, por lo que es la salida más óptima gcc salvar / restaurar / StackFrame de código, en su caso. En MSVC, asm es sobre todo una caja negra para el compilador, para lo cual a menudo / siempre lo peor.

http: // www. ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#ss5.3 , la sintaxis inline asm gcc es más feo, pero con eficacia más eficaz.

  **push        ebp  ;save EBP register
  **mov         ebp,esp  ;Save the stackframe
  **push        ecx  ; So that the variable `m` has an address
;...
  **mov         esp,ebp ;restore the stack frame to it's original address
  **pop         ebp   ;restore EBP register
  **ret ;return from function call

Si se puede hacer una búsqueda en C ++ convenciones de llamada, vas a entender mejor lo que el compilador está haciendo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top