ASM Code

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

ASM Code

Post by counting_pine »

I thought it might be nice to have a thread where people could post little ASM routines and make comments on them. Maybe it will be helpful for people (like me) who are learning or are interested to learn how to use ASM in their programs.
Here's one I cobbled together:

Code: Select all

'reverse the bits in a number, e.g. 0101001 <-> 1001010
function reversebits(byval number as unsigned long, byval bits as long)
    
    if bits<=0 then return 0
    
    asm
        
        mov eax, [number] 'get number
        mov ecx, [bits]   'get bits
        xor ebx, ebx      'result = 0
        
        label1:         'do
        shl ebx, 1          'shift result left
        shr eax, 1          'shift number right
        setc dl             'dl = [bit shr'ed out of number]
        or bl, dl           'add dl to result
        loop label1     'bits -= 1: loop while bits
        
        mov [function], ebx 'function = result
        
    end asm
    
end function
EDIT: Thought I'd post the original non-ASM routine as well.

Code: Select all

function reversebits(byval number as unsigned long, byval bits as long)
    
    dim result as unsigned long
    
    if bits <= 0 then return 0
    
    do
        result shl=1
        result or= number and 1
        number shr=1
        bits-=1
    loop while bits
    
    function = result
    
end function
DrV
Site Admin
Posts: 2116
Joined: May 27, 2005 18:39
Location: Midwestern USA
Contact:

Post by DrV »

Your assembly implementation is not bad, but there are some points that could be improved:

- On modern x86 CPUs, using register halves (ax, al, etc.) causes a pretty large wait.
- "Complex" instructions like LOOP have a lot of overhead versus their more RISC-like counterparts (which might be just a little larger in code size).
Among other things...

Here's a quick translation of your original algorithm with these in mind, plus a little timing code (substitute your original for reversebits and your assembly version for reversebits2):

Code: Select all

function reversebits3(byval number as unsigned integer, byval bits as integer)
	asm
		xor eax, eax		' eax = result
		mov ecx, [bits]		' ecx = bits
		cmp ecx, 0
		jle label3
		
		mov ebx, [number]	' ebx = number
		
		label2:
		
		mov edx, ebx		' edx = number
		shl eax, 1		' result <<= 1
		and edx, 1		' edx = number & 1
		shr ebx, 1		' ebx = number >> 1
		or  eax, edx		' eax = result | (number & 1)
		sub ecx, 1		' bits--
		
		jnz label2		' if (bits) goto label2
		
		label3:
		
		mov [function], eax
	end asm
end function

dim n as unsigned integer, res as unsigned integer, bits as integer
dim count as unsigned integer, max as unsigned integer
dim t1 as double, t2 as double
dim time1 as double, time2 as double, time3 as double

n = &B10001010001000101011010010110101
bits = 32
max = 500000

t1 = timer
for count = 1 to max
	res = reversebits(n, bits)
next count
t2 = timer

time1 = t2 - t1


t1 = timer
for count = 1 to max
	res = reversebits2(n, bits)
next count
t2 = timer

time2 = t2 - t1


t1 = timer
for count = 1 to max
	res = reversebits3(n, bits)
next count
t2 = timer

time3 = t2 - t1

print "1: "; time1; " sec"
print "2: "; time2; " sec"
print "3: "; time3; " sec"
EDIT: added bits <= 0 check

EDIT2: Results from a Pentium II 200MHz:

Code: Select all

1:  1.70704755361658 sec
2:  0.88537437771447 sec
3:  0.387579409667524 sec
It'd be interesting to see how the various implementations stack up on different CPUs...
contrex
Posts: 71
Joined: Dec 10, 2005 12:42

Post by contrex »

P4 3.0 GHz HT/1024M PC3200/WinXP sp2/Shuttle ST62K XPC
1: 0.152801157014437 sec
2: 3.56317391961056e-002 sec
3: 2.57639017054316e-002 sec
Last edited by contrex on Dec 29, 2005 19:58, edited 3 times in total.
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

Post by anonymous1337 »

Pentium 4 2.8ghz processor on Windows XP:
1: 2.81773242168128e-002 sec
2: 2.87466703157406e-002 sec
3: 2.98389879171737e-002 sec
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Post by counting_pine »

P4 2.6GHz, WinXP
1: 4.54063295753713e-002 sec
2: 0.159708845677187 sec
3: 3.86881572937909e-002 sec

Well, that's quite a range of results.

I think I'm going to have to wait a while longer before using ASM, at least until I have an idea of how long different things are likely to take.

Still, it would still be nice to see how other people have used ASM in FreeBASIC, so I'd like to encourage people to carry in posting with more code or comments.
yetifoot
Posts: 1710
Joined: Sep 11, 2005 7:08
Location: England
Contact:

Post by yetifoot »

P4 1.8 Ghz - XP SP2

1: 0.261756731604692 sec
2: 7.59968096390367e-002 sec
3: 6.25043126638047e-002 sec
hippy
Posts: 84
Joined: Nov 04, 2005 18:13
Location: UK

Post by hippy »

AMD K6-2/500 - Win98SE

1: 0.5900157562145978 sec
2: 0.4311101426437745 sec
3: 0.2104343016144412 sec
3apa3a
Posts: 13
Joined: Aug 23, 2005 8:49
Location: Helsinki
Contact:

Post by 3apa3a »

hmm, strange results o_O
P3 700MHZ WinXP

1: 0.361594459187472 sec
2: 0.278808262275561 sec
3: 0.124379181048425 sec
mambazo
Posts: 652
Joined: Jul 17, 2005 13:02
Location: Ireland
Contact:

Post by mambazo »

AMD 64 3800+
WinXP (32-bit)

1: 0.112297512674559 sec
2: 4.84997394923994e-002 sec
3: 2.98929053824395e-002 sec
Drago
Posts: 116
Joined: Aug 10, 2005 13:15

Post by Drago »

P4 640 3,2 GHz
WinXP

1: 0.141670650511514 sec
2: 3.48057630471885e-002 sec
3: 2.55012947600335e-002 sec
DrV
Site Admin
Posts: 2116
Joined: May 27, 2005 18:39
Location: Midwestern USA
Contact:

Post by DrV »

That should be enough variation in CPUs to compare the speeds, thanks.
cha0s
Site Admin
Posts: 5319
Joined: May 27, 2005 6:42
Location: USA
Contact:

Post by cha0s »

there should really be an asm subforum imo.. and a FAQ sub-forum... ahh.. ;p
Deleter
Posts: 975
Joined: Jun 22, 2005 22:33

Post by Deleter »

one more for ya
athlon 64 3700+
winXP (32bit)

Code: Select all

1: 0.1016 sec
2: 3.9603-002 sec
3: 2.6038-002 sec
TheoMcCloskey
Posts: 43
Joined: Aug 04, 2005 21:49
Location: Clifton Park, NY USA

Post by TheoMcCloskey »

and another:

Dell P420, Pentium III, 993 MHz, WinXp 2002 SP1

Code: Select all

1:  .227968 sec
2:  .172678 sec
3:  .763378e-001 sec
DrV
Site Admin
Posts: 2116
Joined: May 27, 2005 18:39
Location: Midwestern USA
Contact:

Post by DrV »

That's plenty, thanks... we don't need to clutter the thread.
Post Reply