Inline assembler

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

Inline assembler

Postby Provoni » Mar 24, 2017 8:55

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: 3127
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Inline assembler

Postby MrSwiss » Mar 24, 2017 10:49

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: 224
Joined: Apr 25, 2008 19:13

Re: Inline assembler

Postby Jawade » Mar 24, 2017 15:12

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

Re: Inline assembler

Postby Provoni » Mar 25, 2017 9:02

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
Posts: 9013
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Inline assembler

Postby fxm » Mar 25, 2017 9:46

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: 224
Joined: Apr 25, 2008 19:13

Re: Inline assembler

Postby Jawade » Mar 25, 2017 12:42

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

Re: Inline assembler

Postby D.J.Peters » Mar 25, 2017 12:59

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: 224
Joined: Apr 25, 2008 19:13

Re: Inline assembler

Postby Jawade » Mar 25, 2017 13:35

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
Posts: 9013
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Inline assembler

Postby fxm » Mar 25, 2017 13:54

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: 224
Joined: Apr 25, 2008 19:13

Re: Inline assembler

Postby Jawade » Mar 25, 2017 15:03

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

Re: Inline assembler

Postby fxm » Mar 25, 2017 16:47

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: 1792
Joined: Jan 02, 2017 0:34
Location: UK

Re: Inline assembler

Postby deltarho[1859] » Mar 25, 2017 19:51

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: 313
Joined: Jan 05, 2014 12:33
Location: Belgium

Re: Inline assembler

Postby Provoni » Mar 26, 2017 8:09

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
Posts: 9013
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Inline assembler

Postby fxm » Mar 26, 2017 8:29

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: 313
Joined: Jan 05, 2014 12:33
Location: Belgium

Re: Inline assembler

Postby Provoni » Mar 26, 2017 9:27

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

Return to “General”

Who is online

Users browsing this forum: albert, Bing [Bot] and 3 guests