Question

J'écrit une fonction asm en Delphi 7, mais il transforme mon code à autre chose:

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;

Pourquoi faut-il générer push ebx et pop ebx? Et pourquoi fait-il mov eax, ebx?

Il semble qu'il génère la trame de pile partielle en raison de la mov eax, ebx.

Ce test simple génère mov eax, edx mais ne génère pas que cadre de pile:

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

Il semble qu'il a quelque chose à voir avec le label err. Si je retire ce que je ne reçois pas la partie mov eax, *.

Pourquoi cela?


Fait un rapport de bogue sur Qualité Central.

Était-ce utile?

La solution

Les conseils pratiques: ne pas utiliser mot-clé étiquette dans le code asm, utilisez @@ - étiquettes préfixés:

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;

Mise à jour :

Je n'ai pas trouvé le rapport de bogue dans zone Basm . Il ressemble à un bug, mais je l'ai utilisé BASM depuis de nombreuses années et n'a jamais pensé à utiliser mot-clé étiquette d'une telle manière. En fait, je jamais utilisé mot-clé étiquette dans Delphi du tout. :)

Autres conseils

Eh bien ... à l'époque, dans le Delphi-Manuel, il l'habitude de dire quelque chose à propos du compilateur-optimisation et thealike-crazyness:


Le compilateur génère Stackframes seulement pour les routines imbriquées, pour Routines ayant des variables locales et des routines avec Stack-Paramètres

Le Initialization- généré automatiquement et Finalizationcode pour Routines comprend:

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 les variables locales contiennent des variantes, des chaînes longues ou interfaces, ils sont initialisés avec nul, mais ne sont pas finalisés par la suite.

Les sections locales est la taille des variables locales, Params la taille des paramètres. Si les deux sections locales ainsi que Params sont nulles pas Init-code sera généré et le Finalizationcode ne contient qu'une RET-intruction.


Peut-être a quelque chose à voir avec tout cela ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top