¿por qué MS C ++ añadir este código para el montaje?
-
19-09-2019 - |
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
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.