flat assembler
Message board for the users of flat assembler.

flat assembler > Non-x86 architectures > [ARM] Reusable Binary Modules: Import+Export Library

Author
Thread Post new topic Reply to topic
m3ntal



Joined: 08 Dec 2013
Posts: 296
Examples of how to export functions to a library (.L) then import them from another module. Easy import+export by name using load and store directives. Create it once then forget about it. Reuse it millions of times.

In version=0: ARM mode. Fast-call a1-a4+v1-v4. 8 parameters maximum. Modular functions, "position independent" with no global references except to functions that are imported in the same order. Any "static" data or literal tables (text and big numbers) must be incorporated inside of the functions and use PC-relative loads. Absolute memory addresses are allowed (example: RAM, VGA, timer, devices).

See ZIP Attachment 4 Updated Magic-ARM Library, Examples, Tests, Disassembler. Scroll down

EXAMPLE LIBRARY: STRING.ASM > STRING.*L
Code:
; EXPORT FUNCTIONS TO STRING.L include 'library.inc' export strlen, strcpy, strcmp, strequ ; strlen(s) - get string length, # characters function strlen, s alias s=a1, b=a2, c=v1 . c=1, b=s .while c ; until 0 . (u8) c=*s++ ; read c .endw . s--, s-b ; return current-start endf ; strcpy(a, b) - standard copy with 0 after function strcpy, a, b alias a=a1, b=a2, c=v1 . c=1 .while c . (u8) c=*b++ ; read . (u8) *a++=c ; copy .endw . a-- ; return end endf ; strcmp(a, b) - lexical comparison. ; return <0> function strcmp, a, b alias a=a1, b=a2,\ c=v1, d=v2 . c=1, d=c .while c=d ; while equal . (u8) c=*a++ . (u8) d=*b++ .if c=0 ; and both nonzero .break .end .if d=0 .break .end .endw . a=c-d ; return *a-*b endf ; strequ(a, b) - equal? return 1/0 function strequ, a, b strcmp .if false return 1 .end endf 0
TEST EXAMPLE.ASM > EXAMPLE.*BIN
Code:
; EXAMPLE. IMPORT FUNCTIONS FROM STRING.L include 'z.inc' import string,\ strlen, strcpy, strcmp, strequ ; example code... nop strcpy 1, 2 strcmp 1, 2
DISASSEMBLY OF STRING+DRAW

Syntaxes generate highly optimized ARM assembler:
Code:
00000000 E92D5FF0 stmdb sp!, {v1-ip,lr} 00000004 E3A04001 mov v1, 1 00000008 E1A01000 mov a2, a1 0000000C E3540000 cmp v1, 0 00000010 0A000001 beq 1Ch 00000014 E4D04001 ldrb v1, [a1], 1 00000018 EAFFFFFB b 0Ch 0000001C E2500001 subs a1, a1, 1 00000020 E0500001 subs a1, a1, a2 00000024 E8BD9FF0 ldmia sp!, {v1-ip,pc} 00000028 E92D5FF0 stmdb sp!, {v1-ip,lr} 0000002C E3A04001 mov v1, 1 00000030 E3540000 cmp v1, 0 00000034 0A000002 beq 44h 00000038 E4D14001 ldrb v1, [a2], 1 0000003C E4C04001 strb v1, [a1], 1 00000040 EAFFFFFA b 30h 00000044 E2500001 subs a1, a1, 1 00000048 E8BD9FF0 ldmia sp!, {v1-ip,pc} 0000004C E92D5FF0 stmdb sp!, {v1-ip,lr} 00000050 E3A04001 mov v1, 1 00000054 E1A05004 mov v2, v1 00000058 E1540005 cmp v1, v2 0000005C 1A000008 bne 84h 00000060 E4D04001 ldrb v1, [a1], 1 00000064 E4D15001 ldrb v2, [a2], 1 00000068 E3540000 cmp v1, 0 0000006C 1A000000 bne 74h 00000070 EA000003 b 84h 00000074 E3550000 cmp v2, 0 00000078 1A000000 bne 80h 0000007C EA000000 b 84h 00000080 EAFFFFF4 b 58h 00000084 E0540005 subs a1, v1, v2 00000088 E8BD9FF0 ldmia sp!, {v1-ip,pc} 0000008C E92D5FF0 stmdb sp!, {v1-ip,lr} 00000090 EBFFFFED bl 4Ch 00000094 E3500000 cmp a1, 0 00000098 1A000001 bne 0A4h 0000009C E3A00001 mov a1, 1 000000A0 E8BD9FF0 ldmia sp!, {v1-ip,pc} 000000A4 E3A00000 mov a1, 0 000000A8 E8BD9FF0 ldmia sp!, {v1-ip,pc} ; Disassembly of DRAW.L: 00000000 E92D5FF0 stmdb sp!, {v1-ip,lr} 00000004 E3A02000 mov a3, 0 00000008 E3822C05 orr a3, a3, 500h 0000000C E0130291 muls a4, a2, a3 00000010 E0933080 adds a4, a4, a1, lsl 1 00000014 E3A01000 mov a2, 0 00000018 E3811602 orr a2, a2, 200000h 0000001C E0910003 adds a1, a2, a4 00000020 E8BD9FF0 ldmia sp!, {v1-ip,pc} 00000024 E92D5FF0 stmdb sp!, {v1-ip,lr} 00000028 E3A02000 mov a3, 0 0000002C E3822602 orr a3, a3, 200000h 00000030 E3A01000 mov a2, 0 00000034 E3811A0B orr a2, a2, 0B000h 00000038 E3811701 orr a2, a2, 40000h 0000003C E3510000 cmp a2, 0 00000040 0A000002 beq 50h 00000044 E0C200B2 strh a1, [a3], 2 00000048 E2511001 subs a2, a2, 1 0000004C EAFFFFFA b 3Ch 00000050 E8BD9FF0 ldmia sp!, {v1-ip,pc} 00000054 E92D5FF0 stmdb sp!, {v1-ip,lr} 00000058 E1A04002 mov v1, a3 0000005C E92D000F stmdb sp!, {a1-a4} 00000060 E3A02000 mov a3, 0 00000064 E3822C05 orr a3, a3, 500h 00000068 E0130291 muls a4, a2, a3 0000006C E0933080 adds a4, a4, a1, lsl 1 00000070 E3A01000 mov a2, 0 00000074 E3811602 orr a2, a2, 200000h 00000078 E0910003 adds a1, a2, a4 0000007C E1A0A000 mov v7, a1 00000080 E8BD000F ldmia sp!, {a1-a4} 00000084 E1A0000A mov a1, v7 00000088 E1C040B0 strh v1, [a1] 0000008C E8BD9FF0 ldmia sp!, {v1-ip,pc} 00000090 E92D5FF0 stmdb sp!, {v1-ip,lr} 00000094 E1A04003 mov v1, a4 00000098 E1A05002 mov v2, a3 0000009C E92D000F stmdb sp!, {a1-a4} 000000A0 E3A02000 mov a3, 0 000000A4 E3822C05 orr a3, a3, 500h 000000A8 E0130291 muls a4, a2, a3 000000AC E0933080 adds a4, a4, a1, lsl 1 000000B0 E3A01000 mov a2, 0 000000B4 E3811602 orr a2, a2, 200000h 000000B8 E0910003 adds a1, a2, a4 000000BC E1A0A000 mov v7, a1 000000C0 E8BD000F ldmia sp!, {a1-a4} 000000C4 E1A0000A mov a1, v7 000000C8 E3550000 cmp v2, 0 000000CC 0A000002 beq 0DCh 000000D0 E0C040B2 strh v1, [a1], 2 000000D4 E2555001 subs v2, v2, 1 000000D8 EAFFFFFA b 0C8h 000000DC E8BD9FF0 ldmia sp!, {v1-ip,pc} 000000E0 E92D5FF0 stmdb sp!, {v1-ip,lr} 000000E4 E1A04003 mov v1, a4 000000E8 E1A05002 mov v2, a3 000000EC E92D000F stmdb sp!, {a1-a4} 000000F0 E3A02000 mov a3, 0 000000F4 E3822C05 orr a3, a3, 500h 000000F8 E0130291 muls a4, a2, a3 000000FC E0933080 adds a4, a4, a1, lsl 1 00000100 E3A01000 mov a2, 0 00000104 E3811602 orr a2, a2, 200000h 00000108 E0910003 adds a1, a2, a4 0000010C E1A0A000 mov v7, a1 00000110 E8BD000F ldmia sp!, {a1-a4} 00000114 E1A0000A mov a1, v7 00000118 E3550000 cmp v2, 0 0000011C 0A000003 beq 130h 00000120 E0D4C0B2 ldrh ip, [v1], 2 00000124 E0C0C0B2 strh ip, [a1], 2 00000128 E2555001 subs v2, v2, 1 0000012C EAFFFFF9 b 118h 00000130 E8BD9FF0 ldmia sp!, {v1-ip,pc}
IMPORT/EXPORT MACROS (IMPORT.INC)
Code:
;;;;;;;;;;;;;;;;;;; IMPORT.INC ;;;;;;;;;;;;;;;;;;; ; write library (.L) file containing ; functions. example: ; export strlen, strcpy, strcmp, strequ macro export [f] { common local n, ..f n=0 forward n=n+1 common ; 16 byte header: db 'L', 0 ; signature, version=0 dh n ; # functions (offset=Ah) dw ..f ; functions begin dw 0, 0 ; reserved forward ; array of: local l l db `f, 0 ; function name times \ ; align 24 24-($-l) \ db 0 dw !#f ; function offset dw !#f#.$ ; function size common while $ mod 4 ; align 4 for ARM db 0 ; (it should already end while ; be aligned) ..f: ; functions begin } ; load s/pecific functions from library*.L ; into current module. example: ; import string,\ ; strlen, strcpy, strcmp, strequ macro import l, [f] { common local a, b, c,\ p, i, n, s, o,\ fb, found, equal virtual at 0 ; virtual file p:: file `l#'.L' end virtual load a byte from p:0 ; signature if a<>'L' 'Invalid signature' end if load a byte from p:1 ; version if a<>0 'Version must be 0' end if load n hword \ ; # functions total from p:2 load fb word \ ; functions begin from p:4 forward ; iterate through local fs ; function names... virtual at 0 fs:: ; current function i=$ ; structure: db `f, 0 ; name times \ ; align 24 24-($-i) db 0 dw 0, 0 ; offset, size end virtual i=0 repeat n ; search functions equal=1 ; for name... found=0 repeat 6-1 ; read and compare load a word from p:\ ; names. 24 bytes, 16+(i*32)+((%-1)*4) ; 4 a time load b word from \ fs:((%-1)*4) if a<>b ; while equal equal=0 break end if end repeat if equal found=16+(i*32) ; offset break end if i=i+1 end repeat if found=0 'Name not found:' f end if load o word from \ ; read offset p:found+24 load s word from \ ; and size p:found+28 store word o at fs:24 ; store in current store word s at fs:28 ; function structure !#f: ; !name: repeat s/4 ; extract found load a word from \ ; function from file p:o+((%-1)*4) ; 4 bytes at a time dw a ; insert <here> end repeat macro f [ps] \{ ; fast-call macro macro list.e a, [p] \ ; store register \\{ \forward \ ; names in list a equ p \\} list.e ?rs,\ v4,v3,v2,v1,\ a4,a3,a2,a1 \forward match x, ?rs ; restore register \\{ restore ?rs ; names let x=ps \\} ; send parameter \common bl !\#f \} common ; ... }


Description:
Filesize: 69.21 KB
Viewed: 3268 Time(s)

library.gif


Description:
Download
Filename: arm_library.zip
Filesize: 124.98 KB
Downloaded: 421 Time(s)



Last edited by m3ntal on 09 Apr 2014, 17:04; edited 1 time in total
Post 09 Apr 2014, 14:51
View user's profile Send private message Reply with quote
m3ntal



Joined: 08 Dec 2013
Posts: 296
Magic-ARM Updates (See Attachment: ARM_LIBRARY.ZIP):

* New TEXT.INC functions: t2i/u/h/b, expand, prefix, enclose, align, skip/copy while/until, array equal/begins
* SYSTEM.INC: Basic memory organization. Increased memory. 8 megabytes by default. @available displays how much memory is remaining at compile-time (Ctrl+F9)
* ARM.INC: Replaced old movi which had a glitch. Now contains 3 movi variations: mov+orr and/or rotate* and movw/t (* not needed in FASMARM, standard mov does this)
* FILE.INC: open/create is binary mode (was "text mode" = automatic translations of return characters)

Tip: To enable ARM Cortex A9 in QEMU for VFP, movw/t, division and Angel ARM semi-hosting, try something like this (where %name%=NAME.BIN):
Code:
qemu-system-arm -cpu cortex-a9 -m 16m -semihosting -kernel %name%
TEXT.INC
Code:
; $$$$$$$$$$$$$$$$$$ MAGIC-ARM $$$$$$$$$$$$$$$$$$$ ; *************** STAR^2 SOFTWARE **************** ; ?????????????????? TEXT.INC ???????????????????? ; fast portable ARM text operations ; text.n t ; get # characters (size-1) ; text.write a, b ; copy with no 0 after ; text.copy a, b ; standard copy with 0 after ; text.copy.n ... ; copy with maximum size ; text.attach a, b ; attach b to a; "concencate" ; text.attach.c... ; attach character ; text.compare a, b ; compare. return <0> ; text.find t, c ; search for c. return &/0 ; text.find.last... ; search for c reverse ; text.count.c t, c ; count occurrances of c ; text.count.n t ; count # lines ; text.begins a, b ; begins with b? ; text.ends a, b ; ends with b? ; text.upper t ; convert to uppercase ; text.lower t ; convert to lowercase ; text.reverse t ; reverse ; text.expand t, n ; shift right ; text.prefix a, b ; prepend ; text.enclose.c... ; enclose in 'c' ; text.align t... ; align to size: '007F' ; text.array.equal ta, t, n ; text.array.begins ta, t, n ; text.skip.while t, type ; text.skip.until t, type ; text.copy.while a, b, type ; text.copy.until a, b, type ; set.source r ; set.token r ; set.stream s, t ; skip.while type ; skip.until type ; copy.while type ; copy.until type ; skip.space ; skip.white ; skip.comment ; skip.all ; i2t n, t ; number/text conversions ; u2t n, t ; h2t n, t ; b2t n, t ; t2i t ; t2u t ; t2h t ; t2b t ;;;;;;;;;;;;;;; CHARACTER TABLES ;;;;;;;;;;;;;;;;; ; ILT - insensitive lookup table. A-Z/a-z are ; the same. increases processing speed by ; many times. example: if (tt[a]=tt[b]) instead ; of: if ((a>='a'&a<='z')&(b>='a'&b<='z')) | ; ((a>='A'&a<='Z')&(b>='Z'&b<='Z')) ; TLT - type lookup table. each byte contains ; C.X BITs to determine its type fast in one ; comparison: if tt[c]&SYMBOL macro define.xlt { align 4 ILT db \ 00h,01h,02h,03h,04h,05h,06h,07h,\ 08h,09h,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh,\ 10h,11h,12h,13h,14h,15h,16h,17h,\ 18h,19h,1Ah,1Bh,1Ch,1Dh,1Eh,1Fh,\ 20h,21h,22h,23h,24h,25h,26h,27h,\ 28h,29h,2Ah,2Bh,2Ch,2Dh,2Eh,2Fh,\ 30h,31h,32h,33h,34h,35h,36h,37h,\ 38h,39h,3Ah,3Bh,3Ch,3Dh,3Eh,3Fh,\ 40h,41h,42h,43h,44h,45h,46h,47h,\ 48h,49h,4Ah,4Bh,4Ch,4Dh,4Eh,4Fh,\ 50h,51h,52h,53h,54h,55h,56h,57h,\ 58h,59h,5Ah,5Bh,5Ch,5Dh,5Eh,5Fh,\ 60h,41h,42h,43h,44h,45h,46h,47h,\ 48h,49h,4Ah,4Bh,4Ch,4Dh,4Eh,4Fh,\ 50h,51h,52h,53h,54h,55h,56h,57h,\ 58h,59h,5Ah,7Bh,7Ch,7Dh,7Eh,7Fh TLT db \ 00h,80h,80h,80h,80h,80h,80h,80h,\ 80h,80h,40h,80h,80h,40h,80h,80h,\ 80h,80h,80h,80h,80h,80h,80h,80h,\ 80h,80h,80h,80h,80h,80h,80h,80h,\ 20h,10h,04h,04h,10h,04h,04h,04h,\ 04h,04h,04h,04h,04h,04h,10h,04h,\ 01h,01h,01h,01h,01h,01h,01h,01h,\ 01h,01h,04h,04h,04h,04h,04h,10h,\ 10h,0Ah,0Ah,0Ah,0Ah,0Ah,0Ah,02h,\ 0Ah,02h,02h,0Ah,02h,0Ah,02h,02h,\ 02h,02h,02h,02h,02h,02h,02h,02h,\ 02h,02h,02h,04h,04h,04h,04h,10h,\ 04h,0Ah,0Ah,0Ah,0Ah,0Ah,0Ah,02h,\ 0Ah,02h,02h,0Ah,02h,0Ah,02h,02h,\ 02h,02h,02h,02h,02h,02h,02h,02h,\ 02h,02h,02h,04h,04h,04h,04h,80h } define.xlt ; 76543210b C.NULL = 00000000b ; 0 C.NUMBER = 00000001b ; 0-9 C.ALPHA = 00000010b ; A-Z, a-z C.SYMBOL = 00000100b ; all symbols except _.?!@$ C.NUMERIC = 00001000b ; A-F/a-f, h,b,k,m/H,B,K,M C.SYMBOLIC = 00010000b ; _.?!@$ C.SPACE = 00100000b ; ' ', '/t' C.RETURN = 01000000b ; 0Dh, 0Ah C.IGNORE = 10000000b ; extended: 1.XXXXXXXb C.KEYWORD = 11111111b C.DIGIT = C.NUMBER or C.NUMERIC C.NAME = C.ALPHA or C.NUMBER or C.SYMBOLIC C.SYMBOLS = C.SYMBOL or C.SYMBOLIC C.ALPHAN = C.ALPHA or C.NUMBER C.VISIBLE = C.ALPHAN or C.SYMBOLS C.WHITE = C.SPACE or C.RETURN C.BLANK = C.WHITE or C.IGNORE C.END = C.SYMBOL or C.WHITE C.0 = 0 ; is c of type? a1=c, a2=type function is.c, c, type . a1&0FFh, a3=TLT, a3+a1 . (u8) a1=*a3, a1&a2 endf macro is.c c, t { . a1=c, a2=t is.c } macro if.is c, t { is.c c, C.#t .if true } numeric ZERO.C='0', SPACE.C=' ',\ COMMA.C=',', COLIN.C=':', SEMI.C=';',\ POUND.C='#', ASSIGN.C='=', SLASHB.C='\' NL equ ,0Dh,0Dh, macro .if.text.equal a, b { !if text.equal, a, b } macro .if.not.text.equal a, b { !if.n text.equal, a, b } macro .if.text.find a, b { !if text.find, a, b } macro .if.text.find.last a, b { !if text.find.last, a, b } macro .if.text.begins a, b { !if text.begins, a, b } macro .if.text.ends a, b { !if text.ends, a, b } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; text.end(t) - advance a1 to end (*t=0) function text.end, t alias t=a1, c=v1 . c=1 .while c ; until 0 . (u8) c=*t++ ; read c .endw . t-- endf ; text.n(t) - get text length, # characters function text.n, t alias t=a1, b=a2, c=v1 . c=1, b=t .while c ; until 0 . (u8) c=*t++ ; read c .endw . t--, t-b ; return current-start endf ; text.write(a, b) - copy with no 0 after function text.write, a, b alias a=a1, b=a2, c=v1 .forever . (u8) c=*b++ ; read .if c=0 return .end . (u8) *a++=c ; copy .endfv endf ; text.copy(a, b) - standard copy with 0 after function text.copy, a, b alias a=a1, b=a2, c=v1 . c=1 .while c . (u8) c=*b++ ; read . (u8) *a++=c ; copy .endw . a-- ; return end endf ; text.copy.n(a, b, n) - copy with maximum ; size specified function text.copy.n, a, b, n alias a=a1, b=a2,\ n=a3, c=v1 .repeat n ; # times . (u8) c=*b++ ; read . (u8) *a++=c ; copy .if c=0 ; end? .break .end .endr . a-- endf ; text.attach(a, b) - attach b to a function text.attach, a, b alias a=a1,\ b=a2, p=v1 . p=b text.end . b=p text.copy endf ; text.attach.c(t, c) - attach c to t function text.attach.c, t, c alias t=a1, c=v2 . c=a2 text.end . (u8) *t++=c, (u8) *t=0 endf ; text.compare(a, b) - lexical comparison. ; return <0> function text.compare, a, b alias a=a1, b=a2,\ c=v1, d=v2 . c=1, d=c .while c=d ; while equal . (u8) c=*a++ . (u8) d=*b++ .if c=0 ; and both nonzero .break .end .if d=0 .break .end .endw . a=c-d ; return *a-*b endf ; text.equal(a, b) - equal? return 1/0 function text.equal, a, b text.compare .if false return 1 .end endf 0 ; text.find(t, c) - search for character. ; return address or 0 function text.find, t, c alias t=a1,\ c=v1, key=a2 .forever ; loop . (u8) c=*t ; read c .if c=0 ; end? return 0 ; not found .end .if c=key ; found? return t ; t=address .end . t++ ; next .endfv endf ; text.find.last(t, c) - search for c reverse function text.find.last, t, c alias t=a1, c=a2,\ key=v1, p=v2 . key=c, p=t ; save begin . c=1 .while c ; advance to end-1, . (u8) c=*t++ ; last character .endw . t-2 .while t>p ; loop backwards . (u8) c=*t ; until beginning .if c=key ; found return t ; t=address .end . t-- ; previous .endw endf 0 ; not found ; text.count.c(t, c) - count # of ; characters in text function text.count.c, t, c alias p=v1, c=v2, n=v3 . p=a1, c=a2, n=0 .while true get p=text.find p, c .if true . p++, n++ .end .endw endf n ; text.count.n(t) - count # lines function text.count.n, t text.count.c a1, 0Dh .if a1>0 . a1++ .end endf ; text.begins(a, b) - a begins with b? function text.begins, a, b alias a=a1, b=a2,\ c=v1, d=v2, e=v3 . c=1, d=c .while c=d ; while equal . (u8) c=*a++ ; load *a/*b . (u8) d=*b++ . e=c|d ; and both nonzero .breakz ; break if either=0 .endw .if d<>0 ; *b must=0 return 0 .end endf ; text.ends(a, b) - a ends with b? function text.ends, a, b alias \ a=v1, b=v2, p=v3 . a=a1, b=a2 text.end ; a=end(a)-length(b) . p=a1, a1=b text.n . p-a1, a1=p, a2=b text.compare .if false return 1 .end endf 0 ; text.upper(t) - convert to uppercase function text.upper, t alias t=a1, c=v1 .forever . (u8) c=*t ; get c .if c=0 ; end? return t .end .if c>=97 ; lowercase? .if c<=122 . c-32 . (u8) *t=c ; copy c .end .end . t++ ; next c .endfv endf ; text.lower(t) - convert to lowercase function text.lower, t alias t=a1, c=v1 .forever . (u8) c=*t ; get c .if c=0 ; end? return .end .if c>=65 ; uppercase? .if c<=90 . c+32 . (u8) *t=c ; copy c .end .end . t++ ; next c .endfv endf ; text.reverse(t) - reverse text function text.reverse, t alias t=a1,\ p=a2, s=a3,\ c=v1, d=v2 . s=t, c=1 ; save start .while c . (u8) c=*t++ ; advance to end .endw . p=t-2, t=s .while t<p ; exchange *t++/*p-- . (u8) c=*t . (u8) d=*p . (u8) *t++=d . (u8) *p=c . p-- .endw . t-- endf ; expand; shift all characters right. ; example: 'abc123' becomes 'XXXabc123' ; after expand 3 where X is unknown function text.expand, t, n alias t=v1, p=v2,\ n=v3, tn=v4, a=v5, b=v6 . t=a1, n=a2 get tn=text.n t . a=t+tn, a--, b=a, a+n .repeat tn . (u8) *a=*b, a--, b-- .endr endf ; insert text at beginning function text.prefix, a, b alias a=v1, b=v2, n=v3 . a=a1, b=a2 get n=text.n b text.expand a, n text.write a, b endf ; enclose t in b/egin and e/nd characters. ; example: text.enclose t, 28h, 29h ; '(', ')' function text.enclose.c, t, b, e alias t=v1, b=v2, e=v3,\ p=v4, n=v5, c=v6 . t=a1, b=a2, e=a3 get n=text.n t text.expand t, 1 . p=t, (u8) *p=b, p=t+n, p++ . (u8) *p++=e, (u8) *p=0 endf ; another way: ; text.copy buffer, b ; text.attach buffer, a ; text.copy a, buffer ; prefix text with c's ('0', ' ', etc) ; or ensure maximum n. example: ; before: text t='7FAB' ; text.align t, 30h, 8 ; after: t='00007FAB', aligned to hex32 function text.align, t, c, n alias t=v1, c=v2,\ n=v4, p=v5, tn=v6 . t=a1, c=a2, n=a3 get tn=text.n t .if n=tn ; same size return ; do nothing .end .if tn>n ; exceeds maximum . t+n, (u8) *t=0 ; end at t+n return .end . n-tn ; expand t text.expand t, n .repeat n . (u8) *t++=c .endr . t+tn, (u8) *t=0 ; terminate endf ; search text array ta for t using text.equal. ; return index or -1 (<0) if not found. ta is ; an array of text addresses (texts) function text.array.equal, ta, t, n alias ta=v1, t=v2,\ n=v3, i=v4, p=v5 . ta=a1, t=a2, n=a3 .loop i=0 to n . p=ta[i] .if.text.equal t, p ; p, t return i .end .endl endf -1 macro .if.text.array.equal ta, t { text.array.equal ta, t, ta#.$ .if r0<>-1 } function text.array.begins, ta, t, n alias ta=v1, t=v2,\ n=v3, i=v4, p=v5 . ta=a1, t=a2, n=a3 .loop i=0 to n . p=ta[i] .if.text.begins p, t return i .end .endl endf -1 macro .if.text.array.begins ta, t { text.array.begins ta, t, ta#.$ .if r0<>-1 } ; 2-DO: insensitive compare and search ;;;;;;;;;;;;;;;;;; CONVERSIONS ;;;;;;;;;;;;;;;;;;; ; x2t(n, t) ; number to text ; convert unsigned 32BIT integer to text function u2t, n, t alias n=a1,\ x=a2, y=a3,\ t=v1, s=v2, c=v3 . t=a2, s=a2 .if n=0 ; zero? . (u8) *t++=30h . (u8) *t=0 return t .end .while n ; until 0 . y=n ; dividend . x=1999999Ah ; ((2^32)/10)+1 . n=n-(n>>>30) ; n=n-(n>>>30) umull c, n, n, x ; n*reciprocal . x=n<<1 . x=x+(x<<2) . x=y-x ; remainder . c=x+30h ; c=(n%10)+'0' . (u8) *t++=c ; *t++=c .endw . (u8) *t=0 text.reverse s endf t ; convert signed 32BIT integer to text function i2t, n, t alias n=a1,\ t=a2, sign=a3 . sign=80000000h .if n&sign ; negate? . -n . (u8) *t++=2Dh ; prepend '-' .end u2t ; convert endf ; convert 32BIT hexadecimal number to text function h2t, n, t alias t=v1, s=v2,\ n=v3, x=v4, hex=v5 . n=a1, t=a2, s=t . hex=_hex .if n=0 ; zero? . (u8) *t++=30h . (u8) *t=0 return t .end .while n ; *t++=*(hex+(n&(16-1))) . x=n&15 ldrb x, [hex, x] ; (u8) x=hex[x] . (u8) *t++=x . n>>>4 ; n/16 .endw . (u8) *t=0 text.reverse s return t _hex: db \ '0123456789ABCDEF' ; 16 bytes endf t ; convert 32BIT binary number to text function b2t, n, t alias t=v1, s=v2,\ n=v3, x=v4 . n=a1, t=a2, s=t .if n=0 ; zero? . (u8) *t++=30h . (u8) *t=0 return t .end .while n ; *t++=(n&1)+'0' . x=n&1, x+30h . (u8) *t++=x . n>>>1 ; n/2 .endw . (u8) *t=0 text.reverse s endf t ; t2x(t) ; text to number ; convert text to unsigned 32BIT integer function t2u, t alias t=v1,\ c=v2, n=v3 . t=a1, (u8) c=*t .if c=30h ; skip preceding .while c=30h ; '0's... . (u8) c=*t++ .endw . t-- .end .if c=0 ; 0 value? return 0 .end . n=0 .forever . (u8) c=*t++ .if c=0 return n .end . n+(n<<2), n+n ; n=n*10+*t++-'0' . n-30h, n+c .endfv endf ; convert text to signed 32BIT integer function t2i, t alias t=v1,\ c=v2, negate=v3 . t=a1, (u8) c=*t . negate=0 .if c='-' ; negative? . t++, negate=1 ; skip .end t2u t .if negate . -a1 .end endf ; convert hexadecimal text to number function t2h, t ; text to hexadecimal alias t=v1,\ c=v2, n=v3 . t=a1, (u8) c=*t .if c=30h ; skip preceding .while c=30h ; '0's... . (u8) c=*t++ .endw . t-- .end .if c=0 ; 0 value? return 0 .end . n=0 .forever . (u8) c=*t++ .if c=0 return n .end . n<<4 ; n=n*16+c2h(*t++) .if c<=39h ; 0-9 . c-30h .else.if c>=97 ; a-f . c-57h .else ; A-F . c-37h .end . n+c .endfv endf ; convert binary text to number function t2b, t ; text to binary alias t=v1,\ c=v2, n=v3 . t=a1, (u8) c=*t .if c=30h ; skip preceding .while c=30h ; '0's... . (u8) c=*t++ .endw . t-- .end .if c=0 ; 0 value? return 0 .end . n=0 .forever . (u8) c=*t++ .if c=0 return n .end . n<<1, n+c ; n=n*2+*t++-'0' . n-30h .endfv endf ;;;;;;;;;;;;;;;;;;;;; PRINT ;;;;;;;;;;;;;;;;;;;;;; ; 2-DO: print formatted text to buffer ;;;;;;;;;;;;;;;;;;; PARSE TEXT ;;;;;;;;;;;;;;;;;;; ; skip while type and not 0 ; get p=text.skip.while p, C.WHITE function text.skip.while, t, type alias t=a1, type=a2,\ c=a3, p=a4, n=v1 .forever . (u8) c=*t .if c=0 return 0 .end .if c=0Ah . p=line.n, (u32) n=*p . n++, (u32) *p=n .end . p=TLT, p+c . (u8) c=*p, c&type .breakz . t++ .endfv . (u8) c=*t .if c=0 return 0 .end endf ; skip until type and while not 0 ; get p=text.skip.until p, C.RETURN function text.skip.until, t, type alias t=a1, type=a2,\ c=a3, p=a4, n=v1 .forever . (u8) c=*t .if c=0 return 0 .end .if c=0Ah . p=line.n, (u32) n=*p . n++, (u32) *p=n .end . p=TLT, p+c . (u8) c=*p, c&type .breakn . t++ .endfv . (u8) c=*t .if c=0 return 0 .end endf ; copy while type and not 0 ; get s=text.copy.while t, s, C.NAME function text.copy.while, a, b, type alias a=a1, b=a2,\ type=a3, c=a4, p=v1, n=v2 .forever . (u8) c=*b .if c=0 go .e .end .if c=0Ah . p=line.n, (u32) n=*p . n++, (u32) *p=n .end . p=TLT, p+c . (u8) c=*p, c&type .breakz . (u8) *a++=*b++ .endfv .e: . (u8) *a=0, (u8) c=*b .if c=0 return 0 .end endf b ; copy until type and while not 0 ; get s=text.copy.until t, s, C.END function text.copy.until, a, b, type alias a=a1, b=a2,\ type=a3, c=a4, p=v1, n=v2 .forever . (u8) c=*b .if c=0 return 0 .end .if c=0Ah . p=line.n, (u32) n=*p . n++, (u32) *p=n .end . p=TLT, p+c . (u8) c=*p, c&type .breakn . (u8) *a++=*b++ .endfv . (u8) *a=0, (u8) c=*b .if c=0 return 0 .end endf b ;;;;;;;;;;;;;;;;;; SOURCE, TOKEN ;;;;;;;;;;;;;;;;; ; safer, easier global skip/copy while/until macro define.source { align 4 void source.p, destiny.p, token.p integer token.type, token.value,\ token.size, line.n, n.lines } macro set.source r { . r12=source.p, r11=r, (u32) *r12=r11 } macro set.token r { . r12=token.p, r11=r, (u32) *r12=r11 } macro set.stream s, t { set.source s set.token t } macro get.source s, t { . s=source.p, (u32) s=*s if ~t eq . t=token.p, (u32) t=*t end if } ; 2-DO... get.destiny fix get.console set.destiny fix set.console save.destiny fix save.console macro get.token.p t { . t=token.p, (u32) t=*t } macro set.token.x x, v { . r12=token#x, r11=v, (u32) *r12=r11 } macro set.token.type v { set.token.x .type, v } macro set.token.class v { set.token.x .class, v } macro set.token.value v { set.token.x .value, v } macro get.token.value x { . x=token.value, (u32) x=*x } ; skip/copy while/until type... function skip.while, type alias p=v1, type=v2 . type=a1 get.source p try p=text.skip.while p, type set.source p endf p function skip.until, type alias p=v1, type=v2 . type=a1 get.source p try p=text.skip.until p, type set.source p endf p function copy.while, type alias p=v1, t=v2, type=v3 . type=a1 get.source p, t try p=text.copy.while t, p, type set.source p endf p function copy.until, type alias p=v1, t=v2, type=v3 . type=a1 get.source p, t try p=text.copy.until t, p, type set.source p endf p macro skip.space { skip.while C.SPACE } macro skip.white { skip.while C.WHITE } macro skip.comment { skip.until C.RETURN } function skip.all alias s=v1, c=v2 .white: try skip.white get.source s . (u8) c=*s .if c=0 return 0 .end .if c=SEMI.C try skip.comment go .white .end endf 1 ; skip spaces then character. return 0 ; if next c not key function skip.c, key alias p=v1,\ c=v2, key=v3 . key=a1 skip.space get.source p . (u8) c=*p .if c<>key return 0 .end . p++ set.source p endf p ; ideas for parsing grammar: ; syntax: parse 'c' ; c=command/s ; '=' ; copy ; '>' ; skip forward ; '<' ; skip reverse ; '>1' ; move right # times ; '<1' ; move left # times ; '>ws' ; skip while space/tab ; '>ur' ; skip until return ; '>w_' ; skip all whitespace ; '>w;' ; skip all+comments ; '=u.' ; copy until end/delimiter ; '=w#' ; while digit ; '=w@' ; while name/identifier ; '>w_=u.' ; skip whitespace then copy ; '=w(a-z|A-Z|0-9|_|.|?)'
Post 09 Apr 2014, 15:56
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 © 2004-2018, Tomasz Grysztar.

Powered by rwasa.