Frage

ich eine asm-Funktion in Delphi 7 geschrieben, aber es verwandelt sich der Code etwas anderes:

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;

Warum generiert es push ebx und pop ebx? Und warum tut sie mov eax, ebx?

Es scheint, dass es den Teilstapelrahmen erzeugt wegen der mov eax, ebx.

Dieser einfache Test erzeugt mov eax, edx erzeugt aber keine dieser Stapelrahmen:

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

Es scheint, dass es etwas mit dem label err zu tun hat. Wenn ich entfernen, dass ich nicht die mov eax, * Teil bekommt.

Warum ist das passiert?


Made einen Fehlerbericht auf Quality Central .

War es hilfreich?

Lösung

Der praktische Rat: Verwenden Sie keine Etiketten Schlüsselwort nicht in asm-Code, Verwendung @@ - Präfix Etikett:

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;

Aktualisiert :

Ich habe nicht den Fehlerbericht in Basm Bereich . Es sieht aus wie ein Fehler, aber ich habe BASM seit vielen Jahren verwendet und nie daran gedacht Etikett mit Keyword eine solche Art und Weise. In der Tat ich Etikett Stichwort überhaupt nicht in Delphi verwendet. :)

Andere Tipps

Nun ... damals in der Delphi-Handbuch, verwendet es etwas über Compiler-Optimierung zu sagen und thealike-Verrücktheit:


Der Compiler erzeugt Stackframes nur für verschachtelte Routinen, für Routinen lokale Variablen mit und für Routinen mit Stapel-Parametern

Die automatisch generierte Initialization- und Finalizationcode für Routinen enthalten:

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

Wenn lokale Variablen Varianten enthalten, lange Strings oder Interfaces sie mit Null initialisiert werden, sind aber danach nicht abgeschlossen.

Die Einheimischen ist die Größe der lokalen Variablen, Params die Größe der Parameter. Wenn sowohl Einheimische als auch Params ist Null kein Init-Kodex wird generiert und der Finalizationcode enthält nur eine RET-Intruction.


Vielleicht hat, dass hat etwas damit zu tun alle ...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top