Pregunta

he escrito una función asm en Delphi 7, pero se transforma mi código a otra cosa:

function f(x: Cardinal): Cardinal; register;
label err;
asm
  not eax
  mov edx,eax
  shr edx, 1
  and eax, edx
  bsf ecx, eax
  jz  err
  mov eax, 1
  shl eax, cl
  mov edx, eax
  add edx, edx
  or  eax, edx
  ret
  err:
  xor eax, eax
end;

// compiled version
f:
  push ebx       // !!!
  not eax
  mov edx,eax
  shr edx, 1
  and eax, edx
  bsf ecx, eax
  jz  +$0e
  mov eax, 1
  shl eax, cl
  mov edx, eax
  add edx, edx
  or  eax, edx
  ret
  err:
  xor eax, eax
  mov eax, ebx   // !!!
  pop ebx        // !!!
  ret

// the almost equivalent without asm
function f(x: Cardinal): Cardinal;
var
  c: Cardinal;
begin
  x := not x;
  x := x and x shr 1;
  if x <> 0 then
  begin
    c := bsf(x); // bitscanforward
    x := 1 shl c;
    Result := x or (x shl 1)
  end
  else
    Result := 0;
end;

¿Por qué se genera push ebx y pop ebx? Y por qué es lo que hace mov eax, ebx?

Parece que genera el marco de pila parcial debido a la mov eax, ebx.

Esta sencilla prueba genera mov eax, edx pero no genera ese marco de pila:

function asmtest(x: Cardinal): Cardinal; register;
label err;
asm
  not eax
  and eax, 1
  jz  err
  ret
  err:
  xor eax, eax
end;

// compiled
asmtest:
  not eax
  and eax, $01
  jz +$01
  ret
  xor eax, eax
  mov eax, edx  // !!!
  ret

Parece que tiene algo que ver con la label err. Si quito que no entiendo la parte mov eax, *.

¿Por qué sucede esto?


Hecho un informe de error en Quality Central .

¿Fue útil?

Solución

El consejo práctico es: no utilizar palabras clave de etiquetas en código ensamblador, uso @@ - prefijo etiquetas:

function f(x: Cardinal): Cardinal; register;
asm
  not eax
  mov edx,eax
  shr edx, 1
  and eax, edx
  bsf ecx, eax
  jz  @@err
  mov eax, 1
  shl eax, cl
  mov edx, eax
  add edx, edx
  or  eax, edx
  ret
@@err:
  xor eax, eax
end;

Actualización

No he encontrado el informe de error en Basm área . Se ve como un insecto, pero he utilizado BASM durante muchos años y nunca pensado en utilizar Etiqueta de palabra clave de tal manera. De hecho nunca he usado la palabra clave etiqueta en Delphi en absoluto. :)

Otros consejos

Bueno ... en ese entonces, en el Delphi-Manual, se utiliza para decir algo sobre Compilador-Optimización y thealike-locura:


El compilador genera Stackframes sólo para rutinas anidadas, para las rutinas que tiene variables locales y para las rutinas con Stack-Parámetros

El Initialization- generada automáticamente y Finalizationcode para las rutinas incluye:

PUSH    EBP              ; If Locals <> 0 or Params <> 0
MOV     EBP,ESP          ; If Locals <> 0 or Params <> 0
SUB     ESP,Locals       ; If Locals <> 0
    ...
MOV     ESP,EBP          ; If Locals <> 0
POP     EBP              ; If Locals <> 0 or Params <> 0
RET     Params           ; Always

Si las variables locales contienen variantes, largas cadenas o interfaces que se inicializan con Null, pero no se han finalizado después.

Los locales es el tamaño de las variables locales, Parámetros del tamaño de los parámetros. Si ambos locales, así como Parámetros son nulos sin Init-código será generado y el Finalizationcode sólo contiene un RET-Intruction.


Tal vez eso tiene algo que ver con todo ...

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