Inline assembler

General FreeBASIC programming questions.
Provoni
Posts: 513
Joined: Jan 05, 2014 12:33
Location: Belgium

Inline assembler

Post by Provoni »

Hey all,

To improve the speed of my program, I am thinking about converting pieces of code to inline asm.

- Are there any recommend compiler options? I have previously tried to use pieces of asm code (provided by forum members) inside my program but the compiler came back with error messages related to the asm code. There seems to be some incompatibility between certain compiler options and inline asm.

- Could using inline asm code break compatibility with other computers, operating systems using the program? My program has a small user base so it should work on a variety of windows machines.

Tyvm
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Inline assembler

Post by MrSwiss »

Provoni wrote:- Could using inline asm code break compatibility with other computers, operating systems using the program?
Yes, if your ASM code is not written, to be compatible with 32 as well as 64 bit OS's,
(or simpler, both FBC versions 32/64), provided you're using the same OS type: e.g. Windows.

Btw. compiler options are, usually not needed ... (except maybe -asm [intel|att]).
Jawade
Posts: 228
Joined: Apr 25, 2008 19:13

Re: Inline assembler

Post by Jawade »

An importatt thing: Don't call the BASIC variables the same as used registernames, like ah, ax etc.
Provoni
Posts: 513
Joined: Jan 05, 2014 12:33
Location: Belgium

Re: Inline assembler

Post by Provoni »

Okay, thank you MrSwiss and Jawade.

There is a problem with the following code, it should loop 10 times (print 1) but instead loops indefinitely. Code snippet from: https://www.tutorialspoint.com/assembly ... _loops.htm

Code: Select all

dim as integer i,j,k,a,b,c
screenres 800,600,32

asm
mov ecx,10
l1:
end asm

print 1

asm
loop l1
end asm

sleep
beep
- mov is short for move? As it moves a value to a register? (ecx)

- A register (ecx) is some sort of hardware variable?

- l1: is a label?
fxm
Moderator
Posts: 12083
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Inline assembler

Post by fxm »

Between the 2 Asm blocks, the register ecx was not saved (version for 32-bit fbc).

Code: Select all

asm
  mov ecx,10
  l1:
  push ecx
end asm

print 1

asm
  pop ecx
  loop l1
end asm

sleep
Last edited by fxm on Mar 26, 2017 8:58, edited 2 times in total.
Jawade
Posts: 228
Joined: Apr 25, 2008 19:13

Re: Inline assembler

Post by Jawade »

You cannot loop or push/pop between 2 different ASM-blocks. It are different worlds.
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: Inline assembler

Post by D.J.Peters »

Jawade wrote:You cannot loop or push/pop between 2 different ASM-blocks. It are different worlds.
you are wrong
the problem are the call to fbPrint or any othe call to the FB runtime lib
destroys your current registers so you have push and pop it.

Joshy
Jawade
Posts: 228
Joined: Apr 25, 2008 19:13

Re: Inline assembler

Post by Jawade »

It should be amazing if that works, it's against aal the rules from the logical coding. I will try it and will see if it 's possible. Thanks.
fxm
Moderator
Posts: 12083
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Inline assembler

Post by fxm »

Similarly with a FB variable as memory, instead of the stack with push/pop (version for 32-bit fbc):

Code: Select all

dim as integer N

asm
  mov ecx,10
  l1:
  mov [N],ecx
end asm

print N

asm
  mov ecx,[N]
  loop l1
end asm

sleep
Last edited by fxm on Mar 26, 2017 8:58, edited 2 times in total.
Jawade
Posts: 228
Joined: Apr 25, 2008 19:13

Re: Inline assembler

Post by Jawade »

It's unbelievable but yes, it works. It is a wonder the program can find the label.
fxm
Moderator
Posts: 12083
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Inline assembler

Post by fxm »

The push/pop version does not work with gcc 32-bit (the one other works) !
(system stack management different from gas, or bug for fbc to gcc 32-bit ?)

However, this works with gcc 32-bit:

Code: Select all

dim as integer N

asm
  mov ecx,10
  l1:
  push ecx
end asm

N += 1

asm
  pop ecx
  loop l1
end asm

print N

sleep
Last edited by fxm on Mar 26, 2017 9:10, edited 3 times in total.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Inline assembler

Post by deltarho[1859] »

It is a wonder the program can find the label.
It is worth remembering that whilst the source code is Assembler, FreeBASIC, and Assembler and both the compiler and we know what 'asm/end asm' means the binary is native code from top to bottom and it has no idea what 'asm/end asm' means but it does know what a relative jump is; and that relative jump is from native code to native code.

Edit: Had a comment here re fxm's last post but it was wrong.
Provoni
Posts: 513
Joined: Jan 05, 2014 12:33
Location: Belgium

Re: Inline assembler

Post by Provoni »

Thanks everyone for jumping in.

However fxm's example with push/pop,

Code: Select all

dim as integer i,j,k,a,b,c 
screenres 800,600,32

asm
  mov ecx,10
  l1:
  push ecx
end asm

print 1

asm
  pop ecx
  loop l1
end asm

sleep
beep
returns errors:

Code: Select all

C:\FreeBASIC-1.05.0-win64\fbc -t 50000 -s gui -O max "asm_test1.bas"
asm_test1.asm: Assembler messages:
asm_test1.asm:42: Error: operand type mismatch for `push'
asm_test1.asm:51: Error: operand type mismatch for `pop'

Make done
It says make done but no executable is generated. Using FbEdit 1.0.7.6c.
fxm
Moderator
Posts: 12083
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Inline assembler

Post by fxm »

This kind of code (with push/pop) works for gas 32-bits only.

For 64-bit fbc (with push/pop), one can use the rcx register:

Code: Select all

dim as integer i,j,k,a,b,c
screenres 800,600,32

asm
  mov rcx,10
  l1:
  push rcx
end asm

print 1

asm
  pop rcx
  loop l1
end asm

sleep
beep
For 64-bit fbc (with not push/pop but a 32-bit FB variable as memory) one can always use the ecx register:

Code: Select all

dim as Long N

asm
  mov ecx,10
  l1:
  mov [N],ecx
end asm

print N

asm
  mov ecx,[N]
  loop l1
end asm

sleep
(obviously, this version also works for 32-bit fbc)
Provoni
Posts: 513
Joined: Jan 05, 2014 12:33
Location: Belgium

Re: Inline assembler

Post by Provoni »

Thanks fxm,

So the 16-bit (ax,bx,cx,dx), 32-bit (eax,ebx,ecx,edx) and 64-bit registers (rax,rbx,rcx,rdx) need to be matched properly to the bits of the variable types used.

The following code is working properly. Though,

- rax has to be set to zero because there was another number in it, is that normal procedure and is "mov rax,0" the proper way to do this?

- "inc rax" is an example operation, I understand correctly that keeping stuff as much as possible in the registers is faster than using variables? For example "inc [a]" is slower.

Code: Select all

dim as integer i,j,k,a,b,c

screenres 800,600,32

i=1000000

asm
	mov rax,0
  	mov rcx,[i]
  	l1:
		inc rax
  	loop l1
  	mov [a],rax
end asm

print a

sleep
Post Reply