Domanda

I scritto una funzione di ASM in Delphi 7, ma si trasforma il mio codice a qualcosa d'altro:

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;

Perché non genera push ebx e pop ebx? E perché fa fare mov eax, ebx?

Sembra che genera lo stack frame parziale causa della mov eax, ebx.

Questo semplice test genera mov eax, edx ma non genera che stack frame:

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

Sembra che ha qualcosa a che fare con la label err. Se rimuovo che non ottengo la parte mov eax, *.

Perché accade questo?


Ha fatto un bug report su Qualità Centrale .

È stato utile?

Soluzione

Il consiglio pratico è: non usare l'etichetta parola chiave nel codice asm, uso @@ - prefisso etichette:

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;

Aggiornamento :

Non ho trovato la segnalazione di bug in Basm zona . Sembra un bug, ma ho usato BASM per molti anni e mai pensato di usare Etichetta parola chiave modo. In realtà non ho mai usato l'etichetta parola chiave a Delfi a tutti. :)

Altri suggerimenti

Beh ... allora, in Delphi-Manual, ha usato per dire qualcosa a proposito del compilatore-Ottimizzazione e thealike-follia:


Il compilatore genera Stackframes solo per routine nidificate, per le routine avere variabili locali e per le routine con Stack-Parameters

L'Initialization- auto-generata e Finalizationcode per le routine comprende:

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

Se le variabili locali contengono varianti, lunghe stringhe o interfacce vengono inizializzati con Null, ma non sono finalizzati in seguito.

La gente del posto è la dimensione delle variabili locali, Params la dimensione dei parametri. Se entrambi i locali così come Parametri sono nulli senza Init-codice verrà generato e l'Finalizationcode contiene solo un RET-Intruction.


Forse questo ha qualcosa a che fare con tutto questo ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top