flat assembler
Message board for the users of flat assembler.

Index > Main > Just Preprocessor? FASM with No Assembler?

Author
Thread Post new topic Reply to topic
uart777



Joined: 17 Jan 2012
Posts: 369
uart777
Is there is a version of FASM+IDE that's just the preprocessor, directives and assembly-time (if/while/etc) statements?

My latest macros convert the instructions without the assembler. No reason to have 100s of unused definitions and reserved names.

Preview: Macros to write ARM machine code:
Code:
;;;;;;;;;;;;;;; DATA + ARITHMETIC ;;;;;;;;;;;;;;;;

enumerate it,\
 and, eor, sub, rsb, add, adc, sbc, rsc,\
 tst, teq, cmp, cmn, orr, mov, bic, mvn

enumerate it,\
 ands, eors, subs, rsbs, adds, adcs, sbcs, rscs,\
 tsts, teqs, cmps, cmns, orrs, movs, bics, mvns

; create "data processing" instruction...

macro @dp it, s {
 macro @#it [p] \{
  \common
  local im
  im=0
  syntax 0
 match =0 :x a=,b=,c=,d, \ ; :x a, b, c, <d>
   ?s p \\{
   match sh n, d \\\{
    verify.sh sh, n
    verify.r a
    if n ?is.r ; shx r
     dd (C.\\\#x shl 28) or \
      (it.\\\#it shl 21) or (s shl 20) or \
      (a shl 12) or (b shl 16) or c or \
      (n shl 8) or (SH.\\\#sh shl 5) or 16
    else ; shx #
     dd (C.\\\#x shl 28) or \
      (it.\\\#it shl 21) or (s shl 20) or \
      (a shl 12) or (b shl 16) or c or \
      (n shl 7) or (SH.\\\#sh shl 5)
    end if
    syntax 1
   \\\}
   if.syntax 0 ; :x a, b, c, ri
    if ~ c ?is.r & c ?is.i
     verify.8 c
     im=1
    end if
     dd (C.\\#x shl 28) or \
      (it.\\#it shl 21) or (im shl 25) or \
      (s shl 20) or (b shl 16) or \
      (a shl 12) or c
   end if
   syntax 1
  \\}
  match =0 :x a=,b=,c, \ ; :x a, b, <c>
   ?s p \\{
   match sh n, c \\\{
    verify.sh sh, n
    verify.r a
    if n ?is.r ; shx r
     dd (C.\\\#x shl 28) or \
      (it.\\\#it shl 21) or (s shl 20) or \
      (a shl 12) or (a shl 16) or b or \
      (n shl 8) or (SH.\\\#sh shl 5) or 16
    else ; shx #
     dd (C.\\\#x shl 28) or \
      (it.\\\#it shl 21) or (s shl 20) or \
      (a shl 12) or (a shl 16) or b or \
      (n shl 7) or (SH.\\\#sh shl 5)
    end if
    syntax 1
   \\\}
   if.syntax 0 ; :x a, b, ri
    if ~ c ?is.r & c ?is.i
     verify.8 c
     im=1
    end if
     dd (C.\\#x shl 28) or \
      (it.\\#it shl 21) or (im shl 25) or \
      (s shl 20) or (b shl 16) or \
      (a shl 12) or c
   end if
   syntax 1
  \\}
  match =0 :x a=,b, ?s p \\{ ; :c r, ri
   if ~ b ?is.r & b ?is.i
    verify.8 b
    im=1
   end if
   dd (C.\\#x shl 28) or \
    (it.\\#it shl 21) or (im shl 25) or \
    (s shl 20) or (a shl 16) or \
    (a shl 12) or b
   syntax 1
  \\}
  match =0 a=,b=,c=,d, \ ; a, b, c, <d>
   ?s p \\{
   match sh n, d \\\{
    verify.sh sh, n
    verify.r a
    if n ?is.r ; shx r
     dd (C.al shl 28) or \
      (it.\\\#it shl 21) or (s shl 20) or \
      (a shl 12) or (b shl 16) or c or \
      (n shl 8) or (SH.\\\#sh shl 5) or 16
    else ; shx #
     dd (C.al shl 28) or \
      (it.\\\#it shl 21) or (s shl 20) or \
      (a shl 12) or (b shl 16) or c or \
      (n shl 7) or (SH.\\\#sh shl 5)
    end if
    syntax 1
   \\\}
   if.syntax 0 ; a, b, c, ri
    if ~ c ?is.r & c ?is.i
     verify.8 c
     im=1
    end if
    dd (C.al shl 28) or \
     (it.\\#it shl 21) or (im shl 25) or \
     (s shl 20) or (b shl 16) or \
     (a shl 12) or c
   end if
   syntax 1
  \\}
  match =0 a=,b=,c, ?s p \\{ ; a, b, <c>
   match sh n, c \\\{
    verify.sh sh, n
    verify.r a
    if n ?is.r ; shx r
     dd (C.al shl 28) or \
      (it.\\\#it shl 21) or (s shl 20) or \
      (a shl 12) or (a shl 16) or b or \
      (n shl 8) or (SH.\\\#sh shl 5) or 16
    else ; shx #
     dd (C.al shl 28) or \
      (it.\\\#it shl 21) or (s shl 20) or \
      (a shl 12) or (a shl 16) or b or \
      (n shl 7) or (SH.\\\#sh shl 5)
    end if
    syntax 1
   \\\}
   if.syntax 0 ; a, b, ri
    if ~ c ?is.r & c ?is.i
     verify.8 c
     im=1
    end if
    dd (C.al shl 28) or \
     (it.\\#it shl 21) or (im shl 25) or \
     (s shl 20) or (b shl 16) or \
     (a shl 12) or c
   end if
   syntax 1
  \\}
  match =0 a=,b, ?s p \\{ ; a, b
   if ~ b ?is.r & b ?is.i
    verify.8 b
    im=1
   end if
   dd (C.al shl 28) or \
    (it.\\#it shl 21) or (im shl 25) or \
    (s shl 20) or (a shl 16) or \
    (a shl 12) or b
   syntax 1
  \\}
  verify @#i
 \}
}

macro @dp [p] {
forward
 @dp p, 0
 @dp p#s, 1
}

; create 32 instructions (* 16 conditions
; each = 512 total variations)

@dp and, eor, sub, rsb, add, adc, sbc, rsc,\
 tst, teq, cmp, cmn, orr, mov, bic, mvn

; test dp instructions...

macro @test.dp {
 @add r5, r7                ; a+b
 @add r5, 0FFh              ; a+i
 @add r5, r6, r7            ; a=b+c
 @add r5, r6, 7             ; a=b+i
 @add r5, r6, lsl r7        ; a=b<<c
 @add r5, r6, lsl 7         ; a=b<<i
 @add r0, r3, r5, lsr r7    ; a=b+(c>>>d)
 @adds r0, r3, r5, lsr 7    ; a=b+(c>>>i)
 @add:ne r0, r1, asr r7     ; ne? a=(b>>c)
 @adds:lt r0, r1, asr 7     ; lt? a=(b>>i)
 @add:gt r0, r3, r5, ror r7 ; gt? a=b+(c<>>d)
 @adds:mi r0, r3, r5, ror 7 ; mi? a=b+(c<>>7) 
}

;;;;;;;;;;;;;;;;;;; CONDITIONS ;;;;;;;;;;;;;;;;;;;

enumerate C,\
 eq, ne, hs, lo, mi, pl, vs, vc,\
 hi, ls, ge, lt, gt, le, al, nv

;;;;;;;;;;;;;;;;; BARREL SHIFTER ;;;;;;;;;;;;;;;;;

; @asr r0, 16 = mov r0, r0, asr 16
; @lsl r1, r2 = mov r1, r1, lsl r2

enumerate SH, lsl, lsr, asr, ror

macro verify.shx x {
 if ~ x in <lsl,lsr,asr,ror>
  'Invalid shift:' x
 end if
}

macro verify.shn n {
 if n<0 | n>31
  'Number exceeds range (0-31): ' n
 end if
}

macro verify.sh x, n {
 verify.shx x
 verify.shn n
}

; write shift instruction...

; @shx asr, r0, 24
; @shx lsl, r1, r2

macro @shx i, a, b {
 verify.r a
 if b ?is.r
  dd 0E1A00000h or (a shl 12) or \
   (b shl 8) or (SH.#i shl 5) or \
   10000b or a
 else if b ?is.i
  verify.sh i, b
  dd 0E1A00000h or (a shl 12) or \
   (b shl 7) or (SH.#i shl 5) or a
 else
  'Source must be R/I: ' b
 end if
}

; create shift instructions...

macro @sh [name] {
forward
 macro @#name [p] \{
  \common
  syntax 0
  match =0 a=,b, ?s p \\{
   @shx name, a, b
   syntax 1
  \\}
  verify @\#name
 \}
}

@sh lsl, lsr, asr, ror

; test shx instructions...

macro @test.sh {
 @lsl r0, r1
 @lsl r0, 7
 @lsr r3, r5
 @lsr r3, 5
 @asr r5, r7
 @asr r5, 7
 @ror r7, r3
 @ror r7, 3
}

;;;;;;;;;;;;;;; LOAD/STORE MULTIPLE ;;;;;;;;;;;;;;

; example: @ldm r0, r1,r2,r3

; [1110/100/0/1/0/0/1/0000/0000000000001110]
;           P U S W L  r0              321

macro @lsm op, r, [p] {
common ?rs=0
forward ?rs=?rs or (1 shl p) ; ?rs|=r
common dd (0Eh shl 28) or \
 (r shl 16) or (op shl 20) or ?rs
}

; @ldm/@stm = ldmia/stmdb or ldmfd/stmfd
; (full descending stack)

macro @ldm r, [p] { common @lsm 89h, r, p }
macro @stm r, [p] { common @lsm 90h, r, p }

; @stm! @13, r0,r1,r2,r3 ; !=pre-index

macro @ldm! r, [p] { common @lsm 8Bh, r, p }
macro @stm! r, [p] { common @lsm 92h, r, p }

;;;;;;;;;;;;;;;;;;; PUSH + POP ;;;;;;;;;;;;;;;;;;;

; example: @push r0,r1,r2,r3 ; a1-a4

macro @push [p] { common @stm! @sp, p }
macro @pop [p] { common @ldm! @sp, p }

; preserve v1-v8 registers+lr for function

macro @pushf { dd 0E92D4FF0h } ; v1-v8, lr
macro @popf { dd 0E8BD8FF0h }  ; v1-v8, pc    
Post 01 Sep 2013, 23:36
View user's profile Send private message Reply with quote
shutdownall



Joined: 02 Apr 2010
Posts: 518
Location: Munich
shutdownall
No assembler doesn't make sense.

Please take notice, that at least data definitions like db, dw, dd and so on are assembly directives. Of course you can disable the X86_64.INC if not used or simply empty this file when deleting the instructions section in TABLES.INC. And I think you don't need AVX.INC any more (after stripping TABLES.INC). I think such a version isn't existing but you can do yourself in a few minutes.

Could be more done to strip it down but this is maybe too much work and you have to go deeper into the code. Wink

And I guess you know, that a complete ARM version of FASM is already existing ?
See section Non-X86-architectures in the forum. Cool
Post 02 Sep 2013, 16:33
View user's profile Send private message Send e-mail Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4240
Location: 2018
edfed
no assembler in fasm means just f


why not, it is an iterresting idea to just have the fasm macro system with a bunch of cpu definitions.
we still have arm, pic12bits and x86, and just one compiler, and the list can grow as fast as we want, (if we want)

personnaly, i find it very interesting, and if we can generate the cpu specific opcodes with a set of universal mnemonics, we can then have the universasm, and then, write in assembly one time, compile and run everywhere (better than java i mean).

with f as a launcher, we can easy have a sort of virtual virtual machine (means real machine). just we have to compile and run, and as fasm is fast, we just have to run.... Smile

keep it up, a f version of fasm can really be interesting. maybe TG can think about it.
Post 02 Sep 2013, 16:43
View user's profile Send private message Visit poster's website Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 619
cod3b453
I seem to have a version of this called "fasmpre" that I had used for this but this looks to now be called "prepsrc" under the tools directory (there's also a listing and symbols dumper).

EDIT: OK not quite this only does preprocessing, sorry
Post 02 Sep 2013, 17:10
View user's profile Send private message Reply with quote
shutdownall



Joined: 02 Apr 2010
Posts: 518
Location: Munich
shutdownall
edfed wrote:
personnaly, i find it very interesting, and if we can generate the cpu specific opcodes with a set of universal mnemonics, we can then have the universasm, and then, write in assembly one time, compile and run everywhere (better than java i mean).


If you like to rename mnemonics, you can do easily yourself while editing the TABLES.INC and compile FASM.

Since now there are only 2 official FASM versions existing - for x86 processors and for the ARM family. But I am not sure if this is not just a private project maintained by revolution. I myself made a version for Zilog Z80 CPUs and Tomek made a Q&D JAVA version based on macros. So I wouldn't count this as a separate FASM version.

The problem is that all targets are quite different and use different instructions. What does it help to change the mnemonics to universal mnemonics when you have to think in different architectures ?

There are maybe some helpful synonyms when you are confused. I myself am sometime confused by using jr (jump relative for Z80) with jmp (jump for x86). But if this justifys a separate version maintained by TG - I don't think so.

But you can do yourself easily, upload the version to Non-x86-architectures and maintain it in future when new releases are posted. Everyone could do.

And why make a new version stripped with functions not needed ? Just because it results a little bit smaller exe file ? Who cares ... There is a reason why FASM is delivered as source code. Everyone can make his own version easily. With keyboard shortcuts for menmonics or whatever you wish. I think if you ask 100 members you get at least 110 versions. Razz

And as stated in my first posting here: There was alreay a FASMARM version existing. I don't know why there is now a macro framework done creating ARM output which could be created with FASMARM ? Shocked
Post 02 Sep 2013, 19:45
View user's profile Send private message Send e-mail Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 2945
Location: vpcmipstrm
bitRAKE
The differences in processor state from instruction to instruction would be very difficult to model. So, an intermediate language would be the least common denominator approach -- loosing all the benefits of programming in assembler. Cross-assembling would have the same limited benefit, depending on architecture commonalities.

From a design perspective it would be interesting to turn FASM inside-out: having a machine independent core consisting of just a pre-processor. All instructions and output formats would be defined in a machine independent way. This would be similar to writing FASM in a HLL, though.
Post 03 Sep 2013, 00:43
View user's profile Send private message Visit poster's website Reply with quote
uart777



Joined: 17 Jan 2012
Posts: 369
uart777
Ok, I'll have to edit FASM.

cod3b453: That's what I'm thinking of but with the assembly-time directives (if/while/etc). Such a project would be valuable for educational purposes: Learning how to create dis/assemblers, compilers, emulators.

shutdownall:

It makes perfect sense. FASMX86+FASMARM have 3,000+ definitions and reserved names/aliases that I'll never use.
Quote:
And I guess you know, that a complete ARM version of FASM is already existing ? See section Non-X86-architectures in the forum.
Uh, I should know having written 12,000+ lines of code for FASMARM Cool For GBA, RPI, WMobile, Angel, PL110, RiscOS.
Quote:
Tomek made a Q&D JAVA version based on macros
Java Assembler for FASM that supports variables, classes, methods and examples: Applet + JFrame
Post 03 Sep 2013, 02:05
View user's profile Send private message Reply with quote
uart777



Joined: 17 Jan 2012
Posts: 369
uart777
shutdownall:
Quote:
And as stated in my first posting here: There was alreay a FASMARM version existing. I don't know why there is now a macro framework done creating ARM output which could be created with FASMARM ?
Who cares if you don't know the reasons? Sorry, I do not owe anyone an explanation and do not need anyone's permission/approval to write code a certain way.

As for FASMARM, I've probably released more code for it than anyone else in this community. After I finish this project, I'll still recommend FASMX86+FASMARM. Mini-ARM Macro Assembler will be provided for programmers who are experienced with FASM's preprocessor and who want to learn ARM machine code and see different techniques for converting instructions.

Example/Excerpt: An easier way to create shx instructions: @lsr r0, 7 = @mov r0, r0, lsr 7. (enumerate creates 0-3 = SH.lsl, SH.lsr, SH.asr, SH.ror):
Code:
enumerate SH, lsl, lsr, asr, ror

irps x, lsl lsr asr ror {
 macro @#x a, b \{
   verify.r a
   if b ?is.r
    dd 0E1A00000h or (a shl 12) or \
     (b shl 8) or (SH.\#x shl 5) or \
     10000b or a
   else if b ?is.i
    verify.sh x, b
    dd 0E1A00000h or (a shl 12) or \
     (b shl 7) or (SH.\#x shl 5) or a
   else
    'Source must be R/I: ' b
   end if
 \}
}    
To verify parameters:
Code:
macro verify.shx s {
 if ~ s in <lsl,lsr,asr,ror>
  'Invalid shift:' s
 end if
}

macro verify.sh s, n {
 verify.shx s
 if n<0 | n>31
  'Number exceeds range (0-31): ' n
 end if
}     
Is register or immediate? Register list must be checked first because eqtype 0 returns true if register index (numeric). r8-r15 are reserved by FASMX86 so @8-@15 are used (@=ARM):
Code:
?is.r fix in <r0,r1,r2,r3,r4,r5,r6,r7,\
   @8,@9,@10,@11,@12,@13,@14,@15>

?is.i fix eqtype 0

?is.m fix eqtype [0]

macro verify.r r {
 if ~ r ?is.r
  'Register expected: ' r
 end if
}

macro verify.i i {
 if ~ i ?is.i
  'Number expected: ' i
 end if
}    
To disassemble ARM binary, try ARMu disassembler.

Thanks for viewing!


Last edited by uart777 on 03 Sep 2013, 07:34; edited 1 time in total
Post 03 Sep 2013, 05:38
View user's profile Send private message Reply with quote
uart777



Joined: 17 Jan 2012
Posts: 369
uart777
Macros to verify the range of numbers. Helpful when making assemblers/compilers:
Code:
macro verify.n n, min, max {
 if n<min | n>max
  'Number outside range: ' n 
 end if
}

macro verify.4 n   { verify.n n, -15, 15 }
macro verify.u4 n  { verify.n n, 0, 15 }
macro verify.8 n   { verify.n n, -255, 255 }
macro verify.u8 n  { verify.n n, 0, 255 }
macro verify.i8 n  { verify.n n, -128, 127 }
macro verify.12 n  { verify.n n, -4095, 4095 }
macro verify.u12 n { verify.n n, 0, 4095 }
macro verify.i12 n { verify.n n, -2048, 2047 }
macro verify.16 n  { verify.n n, -65535, 65535 }
macro verify.u16 n { verify.n n, 0, 65535 }
macro verify.i16 n { verify.n n, -32768, 32767 }    
Post 03 Sep 2013, 06:45
View user's profile Send private message Reply with quote
uart777



Joined: 17 Jan 2012
Posts: 369
uart777
bitRAKE:
Quote:
So, an intermediate language would be the least common denominator approach -- loosing all the benefits of programming in assembler. Cross-assembling would have the same limited benefit, depending on architecture commonalities.
I'm thinking of a LL language that takes advantage of both CPUs; a symbolic, human-readable version of machine code. Only difference between this and writing ARM assembler is the syntax. See right side:
Code:
@add r5, r7                ; a+b
@add r5, 0FFh              ; a+i
@add r5, r6, r7            ; a=b+c
@add r5, r6, 7             ; a=b+i
@add r5, r6, lsl r7        ; a=b<<c
@add r5, r6, lsl 7         ; a=b<<i
@add r0, r3, r5, lsr r7    ; a=b+(c>>>d)
@adds r0, r3, r5, lsr 7    ; a=b+(c>>>i)
@add:ne r0, r1, asr r7     ; ne? a=(b>>c)
@adds:lt r0, r1, asr 7     ; lt? a=(b>>i)
@add:gt r0, r3, r5, ror r7 ; gt? a=b+(c<>>d)
@adds:mi r0, r3, r5, ror 7 ; mi? a=b+(c<>>7)    
Since ARM is the more powerful CPU, it would be best to have X86 emulate ARM. For ARM to model X86 would cause overhead. One ARM instruction can translate to 3-5+ instructions in X86. I could create macros that allow X86 syntax and generate ARM code - a quick, dirty way to convert FASMX86 to ARM - but this syntax is lower-level, a more accurate representation of ARM.

ARM has many advantages over Intel: Powerful arithmetic, conditional execution, instant barrel shift/rotate in same CPU cycle, 3+ operands, fixed instruction width for special optimizations, execute Java bytecode and more.
Post 03 Sep 2013, 09:17
View user's profile Send private message Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc
uart777
Quote:
That's what I'm thinking of but with the assembly-time directives (if/while/etc).

Technically not possible, because assembly-time directives are processed within the same stage as producing opcodes from instructions. Both are therefore mutually dependent on each other's output. The best one could do is full compilation with subsequent disassembly into fasm syntax, possibly using debug symbols to restore label names and to correctly separate data and code definitions.

_________________
Faith is a superposition of knowledge and fallacy
Post 05 Sep 2013, 09:33
View user's profile Send private message Reply with quote
dogman



Joined: 18 Jul 2013
Posts: 114
dogman
Maybe not what you were looking for but http://www.99-bottles-of-beer.net/language-ibm-hlasm-macro-2228.html is an example of using IBM's macro assembler language without any assembly code generation to print out the 99 bottles of beer song Razz (no I did not write this).

I think you may able to do something similar with PL/I's macro processor. It is very powerful but it's been mumble mumble years since I used it so I can't remember. And I can't remember if it works standalone but I think it does.

_________________
Sources? Ahahaha! We don't need no stinkin' sources!
Post 09 Sep 2013, 13:39
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on YouTube, Twitter.

Website powered by rwasa.