Inline assembler

General FreeBASIC programming questions.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Inline assembler

Post by fxm »

'clr rax' is faster than 'mov rax,0'.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Inline assembler

Post by fxm »

I cannot help more because my good knowledge of assembler language stopped after the Motorola 6800 family !
Last edited by fxm on Mar 26, 2017 14:04, edited 1 time in total.
deltarho[1859]
Posts: 4308
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Inline assembler

Post by deltarho[1859] »

The reason for

Code: Select all

asm_test1.asm:42: Error: operand type mismatch for `push'
asm_test1.asm:51: Error: operand type mismatch for `pop'
is because there is no 'push r/m32' or 'pop r/m32' in 64 bit mode.

If we 'push rcx' we are effectively pushing ecx because ecx is the lower 32 bits of rcx.

@Provoni

If you want to write blindingly fast asm, the main reason a BASIC programmer resorts to assembler, then do not think beyond the registers if you can. Instructions which use the register *cx as a counter are notoriously slow. Writing your own 'bare' loop using registers is about twice as fast as a 'bare' '*cx/loop', for example. An assembler programmer who is not looking for speed will quite happily use the string functions such as cmps - readable and convenient. BASIC programmers should not be thinking about readability and convenience when they type 'asm' they should be thinking about speed. Do not 'spare the horses' when it comes to comments - register only code is not readable. If you go back to the code in six months time you will not have a clue what you were doing.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Inline assembler

Post by MrSwiss »

fxm wrote:'clr rax' is faster than 'mov rax,0'
Fastest way to zero a register in ASM:

Code: Select all

xor rax, rax  ' zero rax 64bit
xor eax, eax  ' zero eax 32bit
...
Provoni
Posts: 514
Joined: Jan 05, 2014 12:33
Location: Belgium

Re: Inline assembler

Post by Provoni »

Thanks guys,

@fxm: we still use the 6800 at my job.

@MrSwiss: thank you, will use it.

@deltarho[1859]: I think the following code box shows what you mean with "do not think beyond the registers". The commented loop example which uses the loop instruction is indeed much slower than the uncommented loop example, though I do not know if it is bare. Thanks for your tip to comment the asm.

Code: Select all

dim as integer i,a
dim as double t

screenres 800,600,32

i=1000000000

t=timer

asm 'loop i times
	
	'xor rax,rax  
	'mov rcx,[i]
	'l1:
	'	inc rax
	'loop l1
	'mov [a],rax
	
	xor rax,rax
	mov rcx,[i]
	l1:
	inc rax
	dec rcx
	jnz l1
	mov [a],rax
  	
end asm

print a,timer-t

sleep
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Inline assembler

Post by fxm »

At my job, 6800 then 6809 and 6802 were used until the late 1980s (assembler programming on the HP development chain).
Provoni
Posts: 514
Joined: Jan 05, 2014 12:33
Location: Belgium

Re: Inline assembler

Post by Provoni »

@fxm: then you must easily surpass the 6800 chip in age. We use them in the PDT6800 (portable barcode scanner).

In the following code I want to get the value of an array into a register through a pointer (memory offset). However, I can only get it to return the memory offset:

Code: Select all

'64-bit

screenres 800,600

dim as integer a,sol(10)
dim as integer ptr p1

sol(7)=13
p1=@sol(7)

asm
	
	mov rax,[p1]
	mov [a],rax

end asm

print a

sleep
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Inline assembler

Post by fxm »

Rustic solution like my assembler level (6800 family only):

Code: Select all

'64-bit

screenres 800,600

dim as integer a,sol(10)
dim as integer ptr p1

sol(7)=13
p1=@sol(7)

asm
   
   mov rax,[p1]
   mov rax,[rax]
   mov [a],rax

end asm

print a

sleep
Provoni
Posts: 514
Joined: Jan 05, 2014 12:33
Location: Belgium

Re: Inline assembler

Post by Provoni »

Thanks fxm, assembler is fun.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Inline assembler

Post by fxm »

Remark for dkl

When passing a reference to an Asm blok, it is considered as a pointer an not a dereferenced pointer.

Example:

Code: Select all

' for 32-bit

dim as integer i = 13, a, b, c, d

dim as integer ptr pi = @i
dim byref as integer ri = i

asm
  mov ecx,[i]
  mov [a],ecx
  
  mov ecx,[pi]
  mov ecx,[ecx]
  mov [b],ecx

  mov ecx,[ri]   ' ri is not considered as a reference
  mov [c],ecx
  
  mov ecx,[ri]   ' ri is considered as a pointer
  mov ecx,[ecx]
  mov [d],ecx
end asm

print a
print b
print c
print d

sleep
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: Inline assembler

Post by D.J.Peters »

Hello fxm what would you acceept from ri ?

ri and pi are the same and it's ok.

A reference is the pointer of source not the value.

Or i don't know what you mean.

Joshy
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Inline assembler

Post by fxm »

In the asm block, I hoped that '[ri]' acts as '', like in FB code (where the internal pointer for reference is automatically dereferenced):

Code: Select all

dim shared as integer i = 13

dim as integer ptr pi = @i
dim byref as integer ri = i


print @i, i
print pi, *pi
print @ri, ri

sleep

Code: Select all

4218936        13
4218936        13
4218936        13
Last edited by fxm on Apr 01, 2017 8:34, edited 1 time in total.
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: Inline assembler

Post by D.J.Peters »

Code: Select all

' for 32-bit

dim as integer a=1
dim as integer ptr   pa = @a
dim byref as integer ra = a

asm
  lea ecx,[a]             ' ecx = @a
  inc dword ptr [ecx]     ' *a+=1
end asm

print a
print *pa
print ra

sleep
Provoni
Posts: 514
Joined: Jan 05, 2014 12:33
Location: Belgium

Re: Inline assembler

Post by Provoni »

I am trying to use SSE/MMX instructions to reduce the number of multplication instructions my program has to loop through. It is not working and any help would be appreciated, here is what I have come up with so far with comments on what needs to be done:

Code: Select all

'64-bit

screenres 800,600

dim as long a
dim as long mula(3)
dim as long mulb(3)
dim as any ptr mula_ptr=@mula(0)
dim as any ptr mulb_ptr=@mulb(0)

'xmm0
mula(0)=26
mula(1)=676
mula(2)=17576
mula(3)=456976

'xmm1
mulb(0)=7
mulb(1)=13
mulb(2)=8
mulb(3)=24

asm
	
	'multiplicate mula(0 through 3) by mulb(0 through 3) and store result
	'value should be (7*26)+(13*676)+(8*17576)+(24*456976)
	'the objective is to reduce the number of multiplication instructions from 4 to 1 using SSE/MMX
	 
	mov r8,[mula] 'memory offset mula into r8
	mov r9,[mulb] 'memory offset mula into r9
	
	movaps xmm0,[mula] 'move mula into xmm0
	movaps xmm1,[mulb] 'move mulb into xmm1
	
	mulps xmm1,xmm0 'multiplicate xmm1 by xmm0
	movd [a],xmm1 'get result

end asm

print "value check: ";(7*26)+(13*676)+(8*17576)+(24*456976)
print "asm value  : ";a

sleep
Further information:

Code: Select all

Originally, an SSE register could only be used as four 32-bit single precision floating point numbers (the equivalent of a float in C). SSE2 expanded the capabilities of the XMM registers, so they can now be used as:

2 64-bit floating points (double precision)
2 64-bit integers

4 32-bit floating points (single-precision)
4 32-bit integers

8 16-bit integers

16 8-bit characters (bytes)
https://en.wikibooks.org/wiki/X86_Assembly/SSE
https://software.intel.com/en-us/forums ... pic/279587
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Inline assembler

Post by fxm »

I cannot execute code but I already think that '[mula]' and '[mulb]' represent nothing in an Asm block because these are arrays (with a descriptor structure) and not variables.
Post Reply