1

I want bsr to operate on a 64 bit number. However, the following only works on the lower 32 bits of the input:

function BSR64(const Val: Int64): Integer;
begin
asm
  bsr           eax, [Val]   
...

How do I do this?

I'm compiling in 64 bit mode using Lazarus.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
IamIC
  • 17,747
  • 20
  • 91
  • 154

1 Answers1

1

Access the 64-bit register as follows:

 bsr rax, [val]

eax is the low 32-bits. ax is the low 16, and al is the low 8.

Using a 32-bit register destination implies a 32-bit operand size for memory. BSR requires that they match, like pretty much every other instruction other than movzx and movsx.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Tim
  • 2,708
  • 1
  • 18
  • 32
  • That worked, thanks. But I have a misunderstanding, then. I thought the result is written into eax, so eax would be 0 to 63. – IamIC Feb 06 '15 at 06:23
  • I am not quite sure what you mean here. The result is written to `eax`, but `eax` is the low 32 bits only (bits 0 to 31). I am not sure what your assembler will do in this case since `val` appears to be a 64-bit value, but my guess it that it truncates it copying only the low 32 bits of `[val]`. – Tim Feb 06 '15 at 06:33
  • I mean, the result of a bsr is 0 to 63 on a 64 bit input. I thought "0" to "63" is pushed into eax by the bsr op, meaning its range of only 6 bits easily fits into eax. So I thought that "0" to "63" is written into the dest, not that the dest has to match the source size. – IamIC Feb 06 '15 at 06:37
  • 2
    @IanC: If you write to a 32-bit register in 64-bit mode you "destroy" the high part of the 64-bit register. From Intel: "32-bit operands generate a 32-bit result, **zero-extended** to a 64-bit result in the destination general-purpose register." – rkhb Feb 06 '15 at 08:18
  • It really is a different world to higher level coding. I wouldn't have naturally thought "Read 64 bit input, process, write 32 bit answer" would destroy the upper 32 bits of the input because the output is smaller. I'd need to learn a lot more to fully get why this is so. – IamIC Feb 06 '15 at 08:25
  • 3
    @IanC it doesn't destroy the input, it just doesn't even read it. There is no version of `bsr` that reads 64bits and writes 32bits, both sizes have to be the same. Writing 32bits does destroy the high half of the output register. – harold Feb 06 '15 at 11:23
  • 1
    Why not using the BsrQWord function: http://www.freepascal.org/docs-html/rtl/system/bsrqword.html ? – FPK Feb 07 '15 at 10:06
  • in x86 only rotate through cl, movzx and movsx have src and dst of different sizes, in all other instructions all the parameters must have the same width. For the reason why writing to a 32-bit register destroy the high bits read [Why do x86-64 instructions on 32-bit registers zero the upper part of the full 64-bit register?](https://stackoverflow.com/q/11177137/995714) – phuclv Nov 24 '19 at 06:14