Search code examples
delphiassemblyx86delphi-7basm

Delphi label and asm weirdness?


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.


Solution

  • 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. :)