BitScanForward

General FreeBASIC programming questions.
schooner
Posts: 30
Joined: Jul 27, 2015 20:53

BitScanForward

Post by schooner »

Is there an example of how to access the special hardware instructions BitScanForward, BitScanReverse, and SSE4 PopCount? When checking the FB source code, the keywordTb() words "bsf" and "bsr" can be found, but seem to be inaccessible. SSE4 "popcnt" should be on the to-do list for the programmers. Here is an example of something that does not work:

Function BitScanForward32 naked cdecl (ByVal num as uinteger) As Integer
Asm
bsf eax,dword Ptr [esp+4]
ret
End Asm
End Function
dkl
Site Admin
Posts: 3235
Joined: Jul 28, 2005 14:45
Location: Germany

Re: BitScanForward

Post by dkl »

Hm, it seems to work for me on both win32 and linux-x86, FB 1.03.0. It compiles and runs without problems.

Code: Select all

Function BitScanForward32 naked cdecl (ByVal num as uinteger) As Integer
	Asm
		bsf eax, dword ptr [esp+4]
		ret
	End Asm
End Function

print BitScanForward32(&b100)
output wrote:2
Do you get an error message, or unexpected output, or something else?
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: BitScanForward

Post by D.J.Peters »

What do you mean with "does not work" ?

No problem here on old PENTIUM 4.

Joshy

Code: Select all

Function BitScanForward32 naked cdecl (ByVal num as ulong) As ulong
  Asm
    bsf eax,dword Ptr [esp+4]
    ret
  End Asm
End Function

Function BitScanReverse32 naked cdecl (ByVal num as ulong) As ulong
  Asm
    bsr eax,dword Ptr [esp+4]
    ret
  End Asm
End Function

print BitScanForward32(&B1)
print BitScanForward32(&B10)
print BitScanForward32(&B100)
print BitScanForward32(&B1000)
print BitScanForward32(&B10000)
print BitScanForward32(&B100000)
print BitScanForward32(&B0)
sleep
0
1
2
3
4
5
0
schooner
Posts: 30
Joined: Jul 27, 2015 20:53

Re: BitScanForward

Post by schooner »

My apologies. Bit scans seem to be working fine now here. I do not know why they did not function in my earlier test program. Murphys law I guess.
schooner
Posts: 30
Joined: Jul 27, 2015 20:53

Re: BitScanForward

Post by schooner »

dkl wrote "...FB 1.03.0. It compiles and runs without problems."

That must be for the 32-bit version. Is it possible to compile any assembly instructions yet in 64-bit? It seems to try. The documentation was not clear that inline assembly was ready, or perhaps some extra flags have to be set to get the documented examples to compile.

Here is a method to bit scan ulongs for FB 32-bit versions. It is approximately 10 times faster than software methods.

Code: Select all

#define BSF64(a) BitScanForward32_long(cuint(a),cuint(a shr 32))

Function BitScanForward32_long cdecl (ByVal num_lo as uinteger, ByVal num_hi as uinteger) as uinteger
Asm
	bsf eax,[num_lo]
	jnz bsf1
	bsf eax,[num_hi]
	jz bsf1
	add eax,32
bsf1:
	mov [Function], eax
End Asm
End Function

print BSF64(&b100ull)
print BSF64(&b100000000000000000000000000000000000000ull)
Last edited by schooner on Jul 30, 2015 17:22, edited 1 time in total.
dkl
Site Admin
Posts: 3235
Joined: Jul 28, 2005 14:45
Location: Germany

Re: BitScanForward

Post by dkl »

In general, this style of inline ASM should also work with FB 64bit since version 1.02.0. Due to the use of the C backend, not everything works yet though.
schooner
Posts: 30
Joined: Jul 27, 2015 20:53

Re: BitScanForward

Post by schooner »

Is there a simple 64-bit "Hello World!" type example just to get started? I cannot get the asm AddFive() example in the documentation to compile. It replies:

"addfive.asm:18: Error: incorrect register 'eax' used with 'q' suffix"
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: BitScanForward

Post by MrSwiss »

schooner wrote:"addfive.asm:18: Error: incorrect register 'eax' used with 'q' suffix"
EAX = 32bit
q suffix refers to q (quad Word) = 64 bits
You'll have to use 64bit reference to register too ... RAX in this case.
Last edited by MrSwiss on Jul 30, 2015 15:54, edited 1 time in total.
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: BitScanForward

Post by fxm »

Can you try with this:

Code: Select all

Function AddFive(ByVal num As Long) As Long
    Asm
        mov eax, [num]
        add eax, 5
        mov [Function], eax
    End Asm
End Function

Dim i As Long = 4

Print "4 + 5 ="; AddFive(i)
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: BitScanForward

Post by MrSwiss »

An introduction to x64 assembly can be found here:
http://lomont.org/Math/Papers/2009/Intr ... sembly.pdf
schooner
Posts: 30
Joined: Jul 27, 2015 20:53

Re: BitScanForward

Post by schooner »

MrSwiss,
Thank you but I have already tried other stuff. I was looking for someone to show me code.

fxm,
Thank you, but that is exactly the example that produced the error. There is a 32-bit version of gcc installed at the root directory. I wonder if that could be overriding the FB compiler directives?
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: BitScanForward

Post by fxm »

schooner wrote:fxm,
Thank you, but that is exactly the example that produced the error.
No.
I replaced "Integer" (64-bit) with "Long" (32-bit)!
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: BitScanForward

Post by MrSwiss »

Just a rewrite of fxm example in x64:

Code: Select all

Function AddFive(ByVal num As LongInt) As LongInt  ' the same as Integer in x64
    Asm
        mov rax, [num]
        add rax, 5
        mov [Function], rax
    End Asm
End Function

Dim i As LongInt = 4

Print "4 + 5 = "; AddFive(i)
sleep
schooner
Posts: 30
Joined: Jul 27, 2015 20:53

Re: BitScanForward

Post by schooner »

fmx,
Worked!!! I noticed in the asm output that all values are converted to longs (e.g. no integers), so that may be the trick to asm compilation.

I have run across this type of error before when trying to convert an unsigned long to signed integer in the FB 64-bit assembly. It will not do it properly.
schooner
Posts: 30
Joined: Jul 27, 2015 20:53

Re: BitScanForward

Post by schooner »

MrSwiss,
That is a good example.

How would you translate this C function for BitScanForward?

__CRT_INLINE BOOLEAN BSF(DWORD *Index,DWORD64 Mask) {
LONG64 t;
__asm__ ("bsfq %0,%1" : "=r" (Mask),"=r" (t));
*Index = t;
return Mask!=0;
}
Post Reply