Delphi label and asm weirdness?
Asked Answered
E

2

5

I written an asm function in Delphi 7 but it transforms my code to something else:

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;

Why does it generate push ebx and pop ebx? And why does it do mov eax, ebx?

It seems that it generates the partial stack frame because of the mov eax, ebx.

This simple test generates mov eax, edx but doesn't generate that 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

It seems that it has something to do with the label err. If I remove that I don't get the mov eax, * part.

Why does this happen?


Made a bug report on Quality Central.

Effect answered 7/3, 2010 at 9:20 Comment(3)
please report this as a bug at qc.embarcadero.com/wc/qcmain.aspxBruyn
You asked several "why" questions here, but none of them were answered by the response you accepted. It looks like you really just wanted to know how to jump to a new instruction in Delphi assembler without regard for why your own attempts failed. Is that accurate?Tupungato
I wanted to know basically why this fails and how to fix it. The reason was that I was using labels. Why it generates that code seems to be a delphi compiler bug - whether this really is so I'll find out after a reply to bug report. (Added the bug-report link to the question)Effect
A
7

The practical advice is: do not use label keyword in asm code, use @@-prefixed labels:

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;

Updated:

I have not found the bug report in Basm area. It looks like a bug, but I have used BASM for many years and never thought about using label keyword such a way. In fact I never used label keyword in Delphi at all. :)

Alphard answered 7/3, 2010 at 9:33 Comment(2)
Any idea why does label generate that mov eax, * thingy... Is it a bug? Or just some weird behaviour?Effect
Instead of @@MyLabel, also @MyLabel (with a single "@") is fine in asm..end blocks.Doublefaced
E
1

Well ... back then, in the Delphi-Manual, it used to say something about Compiler-Optimization and thealike-crazyness:


The Compiler generates Stackframes only for nested Routines, for Routines having local Variables and for Routines with Stack-Parameters

The auto-generated Initialization- and Finalizationcode for Routines includes:

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

If local Variables contain Variants, long Strings or Interfaces they are initialized with Null but aren't finalized afterwards.

Locals is the Size of local Variables, Params the Size of Parameters. If both Locals as well as Params are Null no Init-Code will be generated and the Finalizationcode only contains a RET-Intruction.


Maybe that has got something to do with it all...

Elamite answered 1/4, 2010 at 0:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.