Official repository is now on github
https://github.com/EdouardBERGE/rasm (https://github.com/EdouardBERGE/rasm)
Download releases here => https://github.com/EdouardBERGE/rasm/releases (https://github.com/EdouardBERGE/rasm/releases)
Yes! Another assembler!
- DAMN fast assembling (millions of instructions in a blink of an eye)
- integrated crunched sections (LZ48/LZ49/LZ4/ZX7/Exomizer/APlib) + load&crunch on the fly
- CPC cartridge, ZX snapshots, CPC snapshots up to 4M
- save unlimited binaries with or without AMSDOS/HOBETA header
- handle multiple EDSK update or generation simultaneously
- symbols import/export, breakpoint and dependencies export
- ORG checking, unlimited memory workspaces where labels are shared, bank management, structures
- ALL undocumented instructions
- conditionnal macro, unlimited & embeded loops with local labels, switch/case
- floating point engine, mathematical functions, ...
- MAXAM, AS80, UZ80, Pasmo compatibility option
- Amsdos real & Microsoft basic 40bits float support
- English & French documentation
- Uninterrupted support
Keep in mind that msdos version will work ONLY on true msdos with dos4gw.exe extender or Windows 95,98,Millenium (that graphical manager on msdos) without long filenames. Will work with DOS-box too
Thanks to all the people
supporting me
advising me for new functionnalities, ergonomics
reporting bugs
and of course using the tool!
update 0.130
- error messages clean-up
update v0.129
- bugfix read overrun in pre-processor
- bugfix read overrun in snapshot encoding
- bugfix AMSDOS header creation with filename that contains a path
- force memory cleanup with MorphOS
- when a variable cannot be computed, check for directive names to avoid confusion
update v0.128
- bugfix moar memory leaks
- label code clean-up
update v0.127
- bugfix some memory leaks
update v0.126
- Rasm is able to mix LZsegments and contiguous ORG sections
update v0.125
- bugfix EQU with current adress reference and crunched zones integration
update v0.124
- new directive DF/DEFF in order to output Microsoft IEEE-754 40bits real
- pasmo compatibility option for DEFB/DEFW with multiple output and reference to current adress
update v0.123
- new option to treat warnings as errors
- bugfix segfault with empty struct declaration
- bugfix v0.121 regression for INCWAV
- check labels,variables and alias when declare macro name
update v0.122
- proximity label enhancement with macro inception and loops
- new directive MODULE
update v0.121- early stages MODULE support
- APlib Ultra integration (load&crunch + crunched section)
- bugfix segfault when trying to assemble a file that does not exists
- bugfix segfault with opened comment '/*' until the end of the file
- bugfix DEFB calculation with $ after crunched section
- proximity label beginning with BRK will generate an exportable breakpoint
- \ support (experimental)
- LIMIT directive evolution (mostly for #FFFF writing case)
- crunched INCBIN may use offset/length/remap before crunch
update v0.120
- BIT,RES,SET may use deferred shifting value
- BANK directive may use NEXT as parameter to switch to next BANK space
- operator assignment are now supported
- may use tags in filenames with SAVE directive
- warn for huge shifting and force result to zero (as it's an architecture independant operation)
update v0.119
- bugfix ASSERT with extra-parameters
- local labels are also reference for proximity label inside their respective scope
- struct may be indexed (work in progress concerning init and filler)
- RUN directive also set execution adress for SAVE directive and may be used multiple times
- new option -wu in order to make warnings for every unused var, alias or label
update v0.118
- bugfix using variables for size/offset with SAVE directive
- bugfix using variables for size/offset in a loop with INCBIN directive
- bugfix error message causing core dump (when doing macro inception)
- new option to enforce void usage with macro without parameter
- new option for INCBIN to interlace+zigzag tiles
update v0.117
- new spectrum option HOBETA for SAVE directive
- new snapshot 48K output when using spectrum mode
- bugfix error message when trying to export in symbol file an invalid (but not used) EQU
- bugfix PAGE,PAGESET when used with generated label names and defered computation
- bugfix automatic uppercase+remove spaces in formulas for generated names with INCBIN
- bugfix using negative size with INCBIN (will compute filesize + negative size)
update v0.116
- bugfix infinite loop when first file is not found
- bugfix using prefix with generated label name
- bugfix default max limit (no moar 65535)
- bugfix eDSK generation with interlaced sectors (wrong since 0.112)
- bugfix snapshot with moar than 192K of extended RAM
- snapshot now use PPI control value to 0x82 as default
- struct definition allow DEFB,DEFW,DEFI,DEFR to be used without value
- struct usage may use default values of the struct definition
- struct usage allow inline values for each field
- allow use CP with non implicit A register
- allow proximity label without previous global label (mostly for heritage sources)
- more flexibility with DEFS value
- new math functions GET_R, GET_G/GET_V, GET_B to manage amstrad Plus colors
- new math functions SET_R, SET_G/SET_V, SET_B to manage amstrad Plus colors
- new symbol export option to export one file per memory space
- MX chunk support for up to 4M snapshot with ACE emulator
- BANK, PAGE and PAGESET enhancement for 4M snapshot support (now return 16 bits gate array value)
update v0.115
- bugfix preprocessing with multi-line comments
- bugfix unrecognized % for modulo
- new banking BUILDZX directive for ZX Spectrum usage
update v0.114
- new INCBIN options: REMAP, REVERT, VTILES
- new command line option "-oa" to mimic inputname for binary output
- try some file extensions if the input file is not found
- new alias EXA for EX AF,AF'
update v0.113
- trigger an error when dynamic LZ section cannot crunch
- bugfix when trying to crunch an empty section
- dynamic debug options removed
- snapshot & cartridge summary by default
- embedded rasm export all labels and EQU in the info struct
- new math function CEIL
- rasm may handle generated name with INCBIN directive
update v0.112
- bugfix single NOP wasn't increment nop counter ^_^
- bugfix NOP count with ADD/SUB/XOR/AND/CP (IX+n)/(IY+n)
- bugfix in WAV import
update v0.111- error management code cleanup
- new options with directive INCBIN for wav import
- allow EDSK with invalid track sector size or supernumerary tracks if sectors are DATA compliant
- bugfix confusion between generated global labels and local labels for export
- bugfix EQU with generated names AND curly brackets formulas inside a loop
- bugfix invalid REPEAT values will increment the error counter
update v0.110- allow numeric expression beginning with +- bugfix uninitialized memory reads with embedded Rasm
update v0.109
- bugfix crash when trying to save with a negative size
- bugfix crash case with macro and wrong parameter number
- bugfix EDSK update
- IFDEF/IFNDEF now scans for macro names
- TZX/CDT output support (not working)
- RUN directive may use unknown var as parameter
- embedded Rasm may return info struct about errors and symbols
update v0.108
- allow var name beginning with '_'
- CODE directive may retrieve last outputed byte adress
update v0.107
- colored output with Unix terminal
- trigger error if a (VOID) arg is used with a macro which has parameter(s)
- added Vasm syntax ENDREP and ENDREPEAT to end a REPEAT block
- enforce zero result when there is an error in a calculation
- new directives NOEXPORT/ENOEXPORT to disable/enable on demand symbol export
update v0.106
- multi-line comments
update v0.105
- bugfix wrong error with operator+non decimal negative value
- do not allow CALL (IX) or CALL (IY) syntax
- added comments begining with //
- added SIZEOF support for fields of structures
- new directive TICKER to count instruction duration
update v0.104
- BANK again in the same slot keep memory tracking
- no more path simplification (until i solve it!)
update v0.103
- bugfix memory cleanup with embedded rasm
update v0.102
- bugfix 'BREAKPOINT <adress>' export
- bugfix default limit of 65535
- bugfix limit autotest
- bugfix path simplification for dependencies export
- bugfix memory leak when using (VOID) with macro
- new math function to get a random value
update v0.101
- warn if no byte is written to a snapshot
- warn if RUN directive was already used
- bugfix calculation error cases
- bugfix maxam AND/OR/XOR/MOD operator (regression of v0.89)
- UNDEF does not care anymore about variable existence
- better error management with macro and wrong number of parameters
update v0.100
- bugfix crash with zeroed output file
- bugfix moar memory leaks
update v0.99
- new directive UNDEF
- bugfix memory leaks
- bugfix calculations with a function followed by two or more opened parenthesis
update v0.98
- bugfix with snapshot v2 memory size detection
- new optional parameter to get file size when load and crunch on the fly
- new option to remove warnings
- new fake instructions RR,RL,SRL,SRA,SLL,SLA with 16 bits (BC,DE,HL) registers
- preprocessing does not allow empty parameter to avoid confusion
- extended error may suggest a name if a variable/label/alias looks similar to a 'not found' value
update v0.97
- bugfix conditionnal code inhibition with macro declaration
- better alias infinite recursivity detection
update v0.96
- bugfix memory leak in tag translation with PRINT directive
- bugfix negative offset with INCBIN
- bugfix autotests memory handling
- added include path in command line
update v0.95
- allow spaces in tags inside strings with PRINT directive
- display warning if you try to export symbols or breakpoints with snapshot version 2
- proximity label beginning with BRK will generate an exportable breakpoint
- new enhanced LD instructions (see online documentation)
update v0.94
- bugfix using macro parameter inside print quote
- bugfix multiple memory leak with tag replacement
- bugfix command line side effect with wrong option
- better hack in expression calculator for expression beginning with negative value
- better equality processing in expression calculator
- dependencies export do not display preprocessing message anymore
update v0.93
- bugfix RUN gate array configuration
- overriding an alias with a label will trigger an error
- PRINT directive may use escaped chars in strings
- tags BANK,PAGE,PAGESET may be used with current adress $
update v0.92
- bugfix PAGE tag when using BANK in snapshot mode
update v0.91
- bugfix school case with crunched block
- bugfix proximity labels when using loops or macros
- bugfix imbricated IFUSED/IFNUSED
- new directive FAIL will print a message before exiting with an error flag
- label usage may use formula
- escaped codes support in strings (disregarding the current charset)
- PRINT directive may compute formula in strings when using curly brackets
- RUN directive may set the gate array configuration for snapshots
- generated label with negative index will trigger an error
- overriding an alias with a variable will trigger an error
- overriding a variable with an alias will trigger an error
- missing ENDIF at the end of the source will trigger an error
update v0.90
- PROTECT directive does not increase automatic binary size anymore
- bugfix memory leak with proximity labels
- proximity label properties also for EQU aliases
- label declaration may use formula
update v0.89
- bugfix dependencies export
- multiple bugfix in preprocessor
- simplify path of dependencies when possible
- enhanced ASSERT may PRINT additional parameters
update v0.88
- bugfix another cases during preprocessing
update v0.87
- new proximity labels
- rasm is able to use variables inside label names
- INCBIN directive enhanced for WAV import as a CPC sample or DMA list
- REPEAT directive may export internal counter to a variable
- new directive IFUSED & IFNUSED
- new math operator ! for NOT
- new math function PSGVALUE
- rasm return 1 to shell when there is error(s)
- new options to export dependencies (makefile style)
- new option to define variable(s) from command line
- new option for extended error messages
- bugfix cases during preprocessing
- bugfix tags PAGE & PAGESET
- new autotests embedded in Rasm in order to reduce regressions
update v0.86
- fix many bugs in label import
- fix multi-nops
- fix automatic extension for primary source
- fix infinite loop when error on reserved keyword in an expression
update v0.85
- fix regressions introduced by STRUCT code modifications
update v0.84
- new directives STRUCT and ENDSTRUCT, ENDS to create structures
- fix regression introduced with v0.75 and embedded usage (like Arkos Tracker II does)
update v0.83
- NOCODE output must increment current adress in all cases
- new directives DR & DEFR to define REAL values (Amstrad firmware compatible)
update v0.82
- better infinite loop detection
- bugfix while 0 loop (check and disable block)
- repeat until internal counter harmonisation
- alias SL1 for SLL instruction
- remove CLang warnings on Linux
update v0.81
- added special maxam priorities for parenthesis and boolean operators
update v0.80
- bugfix operator > and >=
- bugfix Maxam priorities
update v0.79
- != operator is back with new solver
update v0.78
- DEFS can handle multiple repetition schemas
- alias DM & DEFM for DEFB
update v0.77
- even faster expression calculation
- maxam & AS80 comparison operators are back
update v0.76
- fix solver when using % prefixed binary values and comparison operators or parenthesis
update v0.75
- newer and faster expression calculator without limitations of comparisons
- % may be used as modulo (still used for binary values)
- Intel hexa & binary style support
- Binary prefix 0b fixed
- does not export IX and IY anymore in symbol files
- better error messages when calculating expressions
- boolean operators && and ||
- PUSH & POP may have more than one register in parameters
- NOP may be multiplied specifying a number of repetition in parameter
- alias <> for != comparison operator
- filenames are forced to upper case when saved to EDSK
- Infinite loop detection won't go to infinite loop anymore ^_^
update v0.74
- usage of snapshot directives forces snapshot output
- try to load .asm or .Z80 file if filename given is not found and has no extension
- BREAKPOINT directive may have an additional parameter to set break adress anywhere
- declaring two MACRO with the same name will trigger an error
- bugfix regression of -m option handling
- each REPEAT or WHILE loop export a REPEAT_COUNTER or WHILE_COUNTER variable, locally
update v0.73
- bugfix in snapshot directive
- bugfix in snapshot when using distinct bank instead of banksets
update v0.72
- ability to generate v2 snapshot for M4Wifi
update v0.71
- math functions HI & LO to get high 8 bits or low 8 bits of a pseudo 16 bits value
- @ prefix for octal values
- AS80 assembler compatibility mode (enough to compile CNG player)
update v0.70
- shifting operator >> bugfix
- EDSK face selection bugfix
update v0.69
- added $ prefix for hex values
- added 0xb prefix for binary values
- added shifting operators << and >>
- EDSK update/generation improvements (make backups before use!)
update v0.68
- Morphos compatibility code
- better error messages
- includes or incbin in a disabled section won't warn anymore if file does not exists
- breakpoint in snapshot with BRKC chunk for ACE emulator
- shorter splash text
- unused var cleanup
update v0.67
- bugfix buffer overflow with long filenames for export
- snapshot support unofficial Winape breakpoint chunk
- new directive BREAKPOINT
- labels begining by BRK or @BRK are exported as breakpoint in snapshots
update v0.66
- new conditionnal directives IFDEF and IFNDEF
update v0.65
- snapshot is initialised with standard CRTC values, all audio channels OFF, all inks to deep blue except ink 1 to bright yellow
- new directives SETCRTC and SETCPC to select the CRTC and CPC model with snapshots
- new tag {PAGE} before a label to get the gate array banking value for the bank of a label (ex: #C4 for a label in bank 4)
- new tag {PAGESET} before a label to get the gate array banking value for the bankset of a label (ex: #C2 for a label in bankset 1 or bank 4,5,6,7)
- new variable ASSEMBLER_RASM (set to 1) in order to have conditionnal code
- SAVE may be used to save file in a (new) DSK. I have to work on a update mode
- "checkmode" option to assemble without writing file(s)
- moar comprehensive error message when using illegal register combination
- moar compact splash screen- documentation updated
update v0.64
- bugfix SYMB chunk size
- added optionnal var export in snapshot SYMB chunk
- improve bankset switch control (do not mix bank & bankset of the same pages)
- INCBIN handle negative offset to seek relative to the end of file
- INCBIN special option to disable overwrite control
update v0.63
- snapshot generation (with SYMB chunk support for ACE)
- new directive BANKSET to work with 4 consecutives pages (only in snapshot mode)
- MEND alias for ENDM (and vice versa)
- Added '0x' prefix for hexadecimal values
- Cartridge generation is supposed to work with Rasm on big-endian CPU (like PowerPC)
- INCBIN directive support negative value for "size to read" in order to read a size relative to fullsize
- BANK directive may be used without parameter to open a new memory space
- bugfix UNTIL condition test
updated v0.61
- bugfix var memory leak with data flow
- bugfix preprocessing with data flow not using string endchar
- bugfix var export
- new directive ASSERT
update v0.58
- fixed INC SP encoding (was DEC SP opcode)
updated v0.57
- more flexible preprocessor with macro parameters
- new label prefix tag {BANK} to get the bank where is located a label
updated v0.56
- bugfix contiguous ORG check
- bugfix when a macro is opened for declaration and never closed
- added while/wend check in pre-processing
- now you can call a macro with a local value using prefix tag {eval}
updated v0.55
- bugfix local label internal building
- new directive INCEXO to include and crunch a file with Exomizer 2 (it's not faster than the original cruncher...)
- new directive LZEXO to open a code section that will be crunched after assembly
- licenses of third parties softwares are included in the windows executable and their respective source files
update v0.53
- bugfix CHARSET <start>,<end>,<index>
- bugfix duplicate name check for alias
- new directives INCLZ4, INCZX7 to include and crunch a file with LZ4 or LZX7
- new directives LZX7, LZ4 to open a code section that will be crunched after assembly
- literal values syntax check
updated v052
- bugfix ADD (IY+n), SBC (IY+n) ADC (IY+n) CP (iy+n) were encoded like IX version
- label duplicate name check
- tree search for variables speed up +20%
update v0.51
- bugfix ORG analysis for cartridge generation
- bugfix LIMIT
- bugfix with local labels not found in imbricated macros
update v0.50
- bugfix ORG <adress>,$
- you may use unix relative paths using Windows so there is nothing to change when switching between both OS
update 2017.04.03 - v0.49
- bugfix multiple LZ48/LZ49 block in the same ORG zone
updated first post with v0.48
- bugfix of label calculations when placed after a LZ48/LZ49 block (there is a bug left with more than one LZ section in the same ORG)
- directives SWITCH/CASE/DEFAULT/ENDSWITCH added
- PRINT enhancement
update v0.46 RELEASE CANDIDATE
- bugfix force binary mode when writing files with Windows to avoid extra-bytes
- bugfix with identical local labels when many repeat/while/macro are imbricated
- bugfix when macro parameters are bigger than parameter definitions (led to abnormal end)
- bugfix ADD,SUB,ADC,SBC with IX adressing
- bugfix with a few error messages that did not trigger an error
- bugfix truncate instead of rounding in MAXAM compatibility mode
- bugfix translate $ current adress once for all with EQU
- bugfix intempestive error message when writing symbol file
- EQU aliases may be declared after use (even it's NOT a recommended practice)
- Allow repeat 0 (zero) to disable a block. The block must be correct as there will be a partial decoding for loops
- Allow RES,SET,BIT,LIMIT first parameter to be a variable/EQU
- Added optionnal EQU and variable export
- Added FLOOR function for calculations
- Added STR winape directive
- Added LIST keyword to ignored winape directives
- Added check for REPEAT/WHILE opened but not closed
- Added automatic windows compiler detection for visual studio & Watcom C
- Improved a lot MAXAM compatibility (when using appropriate option)
- bugfix calculations when there is no operator inside a parenthesis block
update v0.42
- calculation chain reviewed
- allow old style label declaration with a starting dot
- allow useless A,register form with ADC,ADD,SBC,SUB
- extended syntax for 8bits index registers
update v0.40
- huge bugfix session (local labels, macro, label tree, alias, ...)
- documentation FR/EN!
update v0.37
- Macro support with curly brackets
- EQU is now managed as an alias
- Added a PROTECT function to prevent overwrite
- several bugfixes (memory issue, macro mixed with repeat, WRITE DIRECT)
update v035
- many bugfixes, RASM is still in beta
- new directives WRITE, BANK, LET, READ, BRK, RUN, PRINT, STOP, CHARSET, INCBIN, SAVE
update v032
- a few fixes, new directives incl48, incl49 to include a binary file and crunch it on the fly
- windows executable
early stage v027
- cleanup
- licence
- comment support
- c++ wrapper
early stage v026
- wip with conditionnal assembling
- verbose mode, debug mode
early stage v024
- local labels, duplicate labels
- AMSDOS header wip
- automatic save
early stage v023
- INCLUDE fix
- error management
early stage v022
- conditionnal loops wip
- symbol export
early stage v021
- conditionnal assembling
- instructions fix
- memory leak fix
early stage v019
- REPEAT wip
early stage v018
- relative adress fix
- CPR building wip
- Visual Studio compatibility
early stage v017
- mathematical functions premices
- current assembly adress management
early stage v016 (2017 february 16th)
- all Z80 instructions supported (thinking about a public beta)
- use CRC to speed up instruction
early stage v015
- cleanup
- a lot of instructions added
- undocumented instructions added
- (IX+n) management
- flexible limit for binary output
early stage v014
- state machine for parsing
- fast translation with expression for constants, etc.
early stage v013
- relative jumps
- RST assembling as an expression
- variables computed on the fly
early stage v012
- CPR building
- crunched zone relocation
- local labels premices
- single quote and double quotes
- INCBIN
early stage v010
- wip crunchzone
early stage v009
- wip computeExpression
early stage v008
- memory dump
- wip push label, push expression
early stage v007
- label premices
- expression management
early stage v004
- preprocessor creates a word list
early stage v001
- preprocessor draft
Quote from: roudoudou on 08:58, 22 February 17
Yes! Another assembler! ;D
Looks interesting. Looking at some of that code I need to brush up on my assembly, but at least my Assembly is better than my C and was wondering if Translate back to C was an option for this Assembler? 8)
Quote from: AMSDOS on 09:58, 22 February 17
Looks interesting. Looking at some of that code I need to brush up on my assembly, but at least my Assembly is better than my C and was wondering if Translate back to C was an option for this Assembler? 8)
I think this is a disassembler job, i can modify my old dizasm to do that
Sorry my suggestion is ridiculous (I think) :-[ I haven't seen an Assembler translate Assembly back to C, it's unusual I think cause it would only be done to write low-level code into an high-level form. Some early Assembly tutorials for the Amstrad used BASIC and then show equivalent Assembly code which was a good approach, in my case I'm perhaps better at Assembly than C.
first official release of Rasm in the first post (only sources today, stand alone executables monday since i do not have a windows dev machine at home)
the license is MIT "expat"
Why do you have to compile the thing itself?
greeting
Quote from: cpcuser on 22:04, 04 March 17
Why do you have to compile the thing itself?
greeting
Quote from: roudoudou on 18:20, 04 March 17
first official release of Rasm in the first post (only sources today, stand alone executables monday since i do not have a windows dev machine at home)
the license is MIT "expat"
wait monday for executables
update 2017.03.06:
- new release v032, a few fixes, new directives incl48, incl49 to include a binary file and crunch it on the fly
- Windows executables
It's a very great job roudoudou. Thanks.
The maxam compability will be a very good point, coz if it's possible to convert a source to your syntax, it's no more possible to assemble the converted source in a maxam assembler.
Do you believe it will be possible to manage the maxam syntax in your assembler ?
Quote from: Golem13 on 12:05, 06 March 17
It's a very great job roudoudou. Thanks.
The maxam compability will be a very good point, coz if it's possible to convert a source to your syntax, it's no more possible to assemble the converted source in a maxam assembler.
Do you believe it will be possible to manage the maxam syntax in your assembler ?
Thanks to you.
I'm afraid by maxam you mean Winape
Making a maxam compatibility is supposed to be easy to do at short term -> there is only to destroy operator priority
Some of winape directive may be translated on the fly like "Write direct -1,-1,<n>" -> "bank <n>"
I'v already made a winape local label style with '@' ;)
Rasm do not have yet macro support (it's planned)
Rasm does not support elseif (and i have not think about it)
Rasm does not support "AND" "OR" "XOR" operator but it should not be a great difficulty to integrate them
At this very moment i made Rasm to save time for my future production (november 2017) so i cannot promise to work on it before :-X
You will need to include also, and at least the few instructions below (not a exhaustive list):
READ filename
INCBIN filename[,offset[,size[,offset_high]]]
LET symbol = value
IFNOT condtion
RUN address
ORG code_address[,output_address]
CHARSET [string,value|byte,value|start,end,value]
From memory, and it's the commands list I use in maxam/winape syntax :-)
Thanks a lot for your skill ! :-*
Quote from: Golem13 on 13:51, 06 March 17
You will need to include also, and at least the few instructions below (not a exhaustive list):
READ filename
INCBIN filename[,offset[,size[,offset_high]]]
LET symbol = value
IFNOT condtion
RUN address
ORG code_address[,output_address]
CHARSET [string,value|byte,value|start,end,value]
From memory, and it's the commands list I use in maxam/winape syntax :-)
Thanks a lot for your skill ! :-*
I've been working hard on new directives to improve winape/maxam compatibility and facilitate the transfert to Rasm
I added to your list the SAVE, BRK and WRITE DIRECT command
There is a command line switch to avoid operator priority and mimic parenthesis with brackets
The assembler can also import symbols (pasmo/winape/rasm) and work on multiple memory set
For example, if your software is supposed to use expansion bank to run code, you may write a code like this
Each
write direct create a new memory set of
64KIn this example there is 3 independent memory set BUT labels are shared
org #2000
mystart
; main code with menu from #2000
dec a
jr z,submenu1
dec a
jr z,submenu2
myend
save "main.bin",mystart,myend-mystart
write direct -1,-1,#C4
org #4000
submenu1
; code code
submenu1end
save "menu1.bin",submenu1,submenu1end-submenu1
write direct -1,-1,#C4
org #4000
submenu2
; code code
submenu2end
save "menu2.bin",submenu2,submenu2end-submenu2
Note: If you use the WRITE DIRECT -1,-1,n syntax
The assembler will write to specifics CPR memory sets
If no SAVE command is used, a CPR will be automatically created, the assembler will write 16K from the first adress written in the bank
You may force CPR writing
Moar testing then release soon ;)
Thanks Golem for suggestions
new release v035 in the first post, many bugfixes and new directives
RASM is still in beta ;)
specific winape directive compatibility:
write direct -1,-1,<n> same as
bank <n> directive
let this useless keyword is ignored like in locomotive Basic
read same as include directive
brk ignored
run <nn> ignored
print print var, text or expression
stop stop assembling
charset [p1,p2[,p3]] same as Winape charset directive
incbin extended parameters
save "file",adr,size save memory region in a file
updated the first post with v0.37
- Macro support with curly brackets
- EQU is now managed as an alias
- Added a PROTECT function to prevent overwrite
- several bugfixes (memory issue, macro mixed with repeat, WRITE DIRECT)
Updated the first post
A quick update today cause v037 was crap...
Rasm is now going into stabilisation phase since all requested functionnalities are implemented
Quote from: roudoudou on 14:11, 16 March 17
Rasm is now going into stabilisation phase since all requested functionnalities are implemented
I worked a lot this night ;D
change pas d'main, j'sens que ça vient!updated the first post with v0.40- huge bugfix session (local labels, macro, label tree, alias, ...)- documentation FR/EN!
(first post modified)
update 2017.03.20 - v0.42- calculation chain reviewed
- allow old style label declaration with a starting dot
- allow useless A,register form with ADC,ADD,SBC,SUB
- extended syntax for 8bits index registers
- documentation FR/EN updated
still some adjustments to do (local labels are buggy)
First release candidate!
Thanks to Golem for intensive testing, now his project compilation is a LOT faster
Manuals will be released soon in a separate ZIP
update 2017.03.28 - v0.46RC
- bugfix force binary mode when writing files with Windows to avoid extra-bytes
- bugfix with identical local labels when many repeat/while/macro are imbricated
- bugfix when macro parameters are bigger than parameter definitions (led to abnormal end)
- bugfix ADD,SUB,ADC,SBC with IX adressing
- bugfix with a few error messages that did not trigger an error
- bugfix truncate instead of rounding in MAXAM compatibility mode
- bugfix translate $ current adress once for all with EQU
- bugfix intempestive error message when writing symbol file
- EQU aliases may be declared after use (even it's NOT a recommended practice)
- Allow repeat 0 (zero) to disable a block. The block must be correct as there will be a partial decoding for loops
- Allow RES,SET,BIT,LIMIT first parameter to be a variable/EQU
- Added optionnal EQU and variable export
- Added FLOOR function for calculations
- Added STR winape directive
- Added LIST keyword to ignored winape directives
- Added check for REPEAT/WHILE opened but not closed
- Added automatic windows compiler detection for visual studio & Watcom C
- Improved a lot MAXAM compatibility (when using appropriate option)
- bugfix calculations when there is no operator inside a parenthesis block
error...... jr nz,vbl
buildcpr
bank 0
di
res 5,(ix+0),b ; store in B the result of the RES
jr $
; generate a sinus table
align 256
sinustable
ang=0
repeat 256
defb 127*sin(ang)
ang=ang+360/256
rend
nop:nop:nop:nop:nop:call vbl;just for fun
tic=0
repeat
if tic<32
defb tic
else
defw tic
endif
tic=tic+0.7
until tic<64
LZ48
repeat 50
dec a
jr z,$+3
inc b
rend
LZCLOSE
vbl
ld b,#f5
in a,(c)
rra
jr nz,vbl
ret
error...
org #2000
mystart
; main code with menu from #2000
dec a
jr z,submenu1
dec a
jr z,submenu2
myend
save "main.bin",mystart,myend-mystart
write direct #C4
org #4000
submenu1
; code code
submenu1end
save "menu1.bin",submenu1,submenu1end-submenu1
write direct #C4
org #4000
submenu2
; code code
submenu2end
save "menu2.bin",submenu2,submenu2end-submenu2
Quote from: cpcuser on 09:55, 30 March 17error...... jr nz,vbl
yep, i have to fix the LZ48 dynamic block since i made a lot of modifications with labels ;)
Quote from: cpcuser on 10:11, 30 March 17
error...
write direct #C4
Error in the code (that was a wrong example), the correct syntax is describe in manual or winape directive page -> write direct -1,-1,#C4
What are these bad examples?
Can not offer functional?
greeting
Quote from: cpcuser on 11:12, 30 March 17
What are these bad examples?
Can not offer functional?
greeting
i will remove them. Did you test on your sources?
updated first post with v0.48
- bugfix of label calculations when placed after a LZ48/LZ49 block (there is a buf left with more than one LZ section in the same ORG)
- directives SWITCH/CASE/DEFAULT/ENDSWITCH added
update 2017.04.03 - v0.49
- bugfix multiple LZ48/LZ49 block in the same ORG zone
updated first post with new .zip
EDIT: i forgot to mentionned PRINT enhancement, it's now possible to format numeric ouput
MyVar=5*70
PRINT 'MyVar=',{INT}MyVar,' pouet pouet'
Avalaible tags: HEX, HEX2, HEX4, HEX8, BIN, BIN8, BIN16, BIN32, INT
update 2017.04.11 - v0.50
- bugfix ORG <adress>,$
- you may use unix relative paths using Windows so there is nothing to change when switching between both OS
updated first post with new release
quick update v0.51
- bugfix ORG analysis for cartridge generation
- bugfix LIMIT
- bugfix with local labels not found in imbricated macros
still working on exomizer integrated compression
new version in a few days (i cannot generate a windows version until a few days for various reasons...)
critical bug found: ADD (IY+n), SBC (IY+n) ADC (IY+n) CP (iy+n) are encoded like IX version >:(
Golem report me that literal values syntax was not checked: LD A,5CCF (if you forget the : separator) won't warn but the CCF will be omit at the assembly. I fix this and add error messages.
There was no check for duplicate name between labels and variables, now it's ok
I was afraid to lose some speed so i add the same tree search for variables to speed up again the assembling (+20% faster)
See you soon
updated first post with executable of v052
documentation need a strong update now! Soon... :)
I look forward one day (hopefully) to use this and its cartridge features!
One day...
v0.53
- bugfix CHARSET <start>,<end>,<index>
- bugfix duplicate name check for alias
- new directives INCLZ4, INCZX7 to include and crunch a file with LZ4 or LZX7
- new directives LZX7, LZ4 to open a code section that will be crunched after assembly
Manuals and executables updated in the first post
updated first post 2017.05.21 - v0.55
- bugfix local label internal building
- new directive INCEXO to include and crunch a file with Exomizer 2 (it's not faster than the original cruncher...)
- new directive LZEXO to open a code section that will be crunched after assembly
- documentation updated (now with quick access in the summary)
- licenses of third parties softwares are included in the windows executable and their respective source files
updated first post 2017.05.28 - v0.56
- bugfix contiguous ORG check
- bugfix when a macro is opened for declaration and never closed
- added while/wend check in pre-processing
- now you can call a macro with a local value using prefix tag {eval} (will be documented)
updated first post 2017.07.20 - v0.57
- more flexible preprocessor with macro parameters
- new label prefix tag {BANK} to get the bank where is located a label
documentation update in a few days
doc updated 8)
Quote from: Sykobee (Briggsy) on 15:23, 02 May 17
I look forward one day (hopefully) to use this and its cartridge features!
One day...
1 minute test ;D
update 2017.08.02 - v0.58
- fixed INC SP encoding (was DEC SP opcode :picard: )
:doh: :doh: :doh:
minor update 2017.09.15
some improvements in the documentation (that nobody reads anyway since everyone asks me obvious and documented questions. :P :P :P [size=78%] [/size][/size][size=78%])[/size]
updated first post 2017.10.10 - v0.61
- bugfix var memory leak with data flow
- bugfix preprocessing with data flow not using string endchar
- bugfix var export
- new directive ASSERT
Hey, some news!
Originally Rasm was designed for the release of CRTC³ (cartridge mode, banking, ...)
As i plan to release a few things on CPC i will extend Rasm banking management to make snapshots (up to 576K)
Will it be usefull to allow user to set (a few) snapshot settings? (CRTC, registers?)
Not in my opinion as i'm used to do all initialisations with cartridge but...
Let me know :)
First of all: Thanks for the great work (both prods). It's good to see that this nice ASM project goes on.
Second, personally I don't care about Snapshot stuff and so on, as long as it runs on the native CPC / Plus machines. :) But maybe it can help some guys during development of their stuff.
As suggested to me by a few people:
- incbin will handle negative size (to include size-value binary file)
- nocode behaviour will change
- snapshot will include SYMB chunk (supported by ACE emulator) on demand
SYMB chunk in snapshot:
1 byte : symbol name size
n byte(s) : symbol name (without 0 terminator as we know the size)
6 bytes : reserved
2 bytes : with a shitty big endian adress for the symbol
this struct repeated until the chunk size is reached
Quote from: roudoudou on 16:16, 30 November 17
2 bytes : with a shitty big endianusing the only logical endianness adress for the symbol
:)
Everything looks awesome, except... instead of '&','$' or '0x', it only supports '#' for hex values!? What? :picard2:
Quote from: pelrun on 08:29, 02 December 17
Everything looks awesome, except... instead of '&','$' or '0x', it only supports '#' for hex values!? What? :picard2:
$ is used since 30 years by (almost?) all Z80 assemblers for current assembling adress.
What assembler do you use? :o
I may support 0x for hexa but if you want C style hex value you may admit the & stand for AND a nothing else. Be coherent ;D
Yes, $ *by itself* is the current address. And & *by itself* is 'AND'. As prefixes for numbers they are distinct, and can be readily parsed as such.
But I see you've rolled your own lexer and parser, so I suppose you can be given a little slack for not being able to support everything. But it's still a sour note for me.
Quote from: pelrun on 13:17, 02 December 17
Yes, $ *by itself* is the current address. And & *by itself* is 'AND'. As prefixes for numbers they are distinct, and can be readily parsed as such.
But I see you've rolled your own lexer and parser, so I suppose you can be given a little slack for not being able to support everything. But it's still a sour note for me.
'0x' prefix for hex value will be available in the next release, so the syntax will be completely consistent. that was not a big deal to add this but i wont add '&' prefix for the same reason.
I don't actually care about '0x', I just included it for completeness. I don't like # at all, it's weird and rasm specific, but then it's not my assembler or my choice to make.
That's absolutely not specific to Rasm
# is prefix for hexa in MAXAM and DAMS syntax since 1985 ;D
Those who do not integrate this syntax are curious
Both MAXAM and DAMS are Amstrad CPC assemblers
Rasm was designed as a cool transition from old assemblers. That's why there is also a maxam compatibility flags for very old sources with wrong operator priority everywhere
You might want to look at MAXAM again, all the code I can find, including IN THE MANUALS uses &.
DAMS, I have no knowledge of.
In any case, this is completely moot. I voiced my opinion, you said you won't change it, there's nothing left to discuss.
Quote from: pelrun on 16:42, 02 December 17
You might want to look at MAXAM again, all the code I can find, including IN THE MANUALS uses &.
DAMS, I have no knowledge of.
In any case, this is completely moot. I voiced my opinion, you said you won't change it, there's nothing left to discuss.
Page 142 of MAXAM manual -> Hexadecimal numbers by "&" or "#"
So that not weird to choose '#' for hex values, that's clever to support the common hex syntax of the two oldest and widely used Z80 assemblers :P
I remember '&' being the standard hex prefix back in the day, far more than #. I'd have to double check.
This may be a UK/not-UK thing.
Supporting 0x is pretty nice IMO, as rasm is modern.
First post updated with binary and documentation
update 2017.12.03 - v0.63
- snapshot generation (with SYMB chunk support for ACE)
- new directive BANKSET to work with 4 consecutives pages (only in snapshot mode)
- MEND alias for ENDM (and vice versa)
- Added '0x' prefix for hexadecimal values
- Cartridge generation is supposed to work with Rasm on big-endian CPU (like PowerPC)
- INCBIN directive support negative value for "size to read" in order to read a size relative to fullsize
- BANK directive may be used without parameter to open a new memory space
- bugfix UNTIL condition test
Documentation lightly updated
On v0.64 i will upgrade snapshot management and documentation to detail the workflow
Sykobee: In France there was a wellknown magazine (Amstrad 100%) with assembly initiation using DAMS so i guess that's why many french guys are used to # prefix. The logon system had a section for them where they release DAMS sources also.
first post updated with v0.64
(mostly snapshot related evolutions and fix)
- bugfix SYMB chunk size
- added optionnal var export in snapshot SYMB chunk
- improve bankset switch control (do not mix bank & bankset of the same pages)
- INCBIN handle negative offset to seek relative to the end of file
- INCBIN special option to disable overwrite control
- Documentation updated
Quote from: roudoudou on 08:23, 05 December 17
first post updated with v0.64
Can't wait for v1.28 :P Thank's for the update, I will post in other-language forums! :)
v0.65 is coming (need moar testing)
- new prefix {PAGE} for labels, in order to retrieve gate array banking value (useful in snapshot mode) #C0,#C4,#C5,...
Maybe it can be interresting to have a {PAGESET} prefix when banking 64K? #C2,#CA,#D2,...
- SAVE may be used to save file in a (new) DSK. I have to work on a update mode
SAVE"filename",begin,size ; raw export
SAVE"filename",begin,size,AMSDOS ; export with amsdos header
SAVE"filename",begin,size,DSK,"dskname" ; create a dsk and save filename on it
SAVE"filename",begin,size,DSK,"dskname",B ; side B select to save filename
SAVE"filename",begin,size,DSK ; save filename on last deckared DSK and last side used (rasm can handle as many DSK as you want in the same time)
SAVE"filename",begin,size,DSK,A ; current DSK, back to side A
- "checkmode" option to assemble without writing file(s)
- moar comprehensive error message when using illegal register combination
- moar compact splash screen
Need to update documentation too
Update v0.65
- snapshot is initialised with standard CRTC values, all audio channels OFF, all inks to deep blue except ink 1 to bright yellow
- new directives SETCRTC and SETCPC to select the CRTC and CPC model with snapshots
- new tag {PAGE} before a label to get the gate array banking value for the bank of a label (ex: #C4 for a label in bank 4)
- new tag {PAGESET} before a label to get the gate array banking value for the bankset of a label (ex: #C2 for a label in bankset 1 or bank 4,5,6,7)
- new variable ASSEMBLER_RASM (set to 1) in order to have specific rasm code
- SAVE may be used to save file in a (new) DSK. I have to work on a update mode
- "checkmode" option to assemble without writing file(s)
- moar comprehensive error message when using illegal register combination
- moar compact splash screen
- documentation updated
updated first post with v0.66
- new directives IFDEF, IFNDEF to test label, variable or alias existence
Always at the top.
Thank you Roudoudou.
updated first post 2017.12.21 - v0.67
- bugfix buffer overflow with long filenames for export
- export breakpoint in snapshot (unofficial Winape chunk)
- new directive BREAKPOINT
Labels begining with BRK or @BRK for local labels will be exported as breakpoints in the snapshots
buildsna
bankset 0
run 0
nop
breakpoint
ld hl,#1234
breakpoint
ld hl,#1234
repeat 2
nop
@brktest
ld hl,#1234
nop
rend
brknext
ld hl,#1234
nop
(at least in ACE it's official :))
Quote from: CloudStrife on 11:55, 22 December 17
(at least in ACE it's official :) )
It's a great news because we will have at least 3 emulators with snapshot breakpoint support as Lone annonced next release of Sugarbox will do.
Kevin? You know what to do ;D
Quote from: CloudStrife on 11:55, 22 December 17
(at least in ACE it's official :) )
Need to specify: by the chunk descripted here:
http://www.cpcwiki.eu/index.php/Snapshot#BRKC_Chunk_.28ACE.29
(not the same as WinAPE and more evolved)
Quote from: CloudStrife on 14:56, 26 December 17
Need to specify: by the chunk descripted here:
http://www.cpcwiki.eu/index.php/Snapshot#BRKC_Chunk_.28ACE.29 (http://www.cpcwiki.eu/index.php/Snapshot#BRKC_Chunk_.28ACE.29)
(not the same as WinAPE and more evolved)
ok, not the same
will add the support for this one, thanks!
Hello,
I found (with the help of CPPCheck, that run on the wrong folder ;D ) some potential bugs in RASM (version 0.67) :
- rasm_v067.c line 1589 : Message: Returning/dereferencing 'subchunk' after it is deallocated / released
- rasm_v067.c line 1594 : Common realloc mistake: 'subchunk' nulled but not freed upon failure
- rasm_v067.c line 3308 : Memory leak: data
- rasm_v067.c line 6782, 6783, 6807, 6831 : Uninitialized variable: mypc
By the way, any plan for a new release soon ?
Thanks! I will take a look
I fix some (minor) bugs this month so...
Maybe a release soon
New release, nothing really significant for users, except...
...Rasm does not warn anymore if there is an include of a missing file in a disabled code section
I finally manage to handle the case without loss of speed nor heavy modifications
Yeeeeeess! :).
documentation lightly updated (there is a glitch in the english index table, don't know how to remove it but it's still usable)
Valentine's release v0.69
- added $ prefix for hex values
- added 0b prefix for binary values
- added shifting operators << and >>
- EDSK update/generation improvements (make backups before use!)
Thanks for the update! Yay! :) :) :) Just un idea, if future can you rename "manual" to "RASM_manual" or similar, after a while it's confusing to have multiple "manual" files in disc. :)
Quote from: GUNHED on 15:41, 15 February 18
Thanks for the update! Yay! :) :) :) Just un idea, if future can you rename "manual" to "RASM_manual" or similar, after a while it's confusing to have multiple "manual" files in disc. :)
Sure
Will do it for next release
Quote from: roudoudou on 13:14, 15 February 18
Valentine's release v0.69
- added $ prefix for hex values
- added 0xb prefix for binary values
- added shifting operators << and >>
- EDSK update/generation improvements (make backups before use!)
Ah ah ah! Petit coquinou !
What a strange version name (0.69) for valentine ´s day !
What a joker you are!
MacDeath will be happy about that 😋
a quick update cause of shifting operator >> did not work...
now shrinkler sources can compile
update v071
- math functions HI & LO to get high 8 bits or low 8 bits of a pseudo 16 bits value
- @ prefix for octal values
- AS80 assembler compatibility mode* (enough to compile CNG player with the same wrong calculations :P )
short doc
Quote
-ass AS80 behaviour mimic
- all calculations are done with 32 bits integer values and wrong rounding
- macro parameters are not protected with {} anymore
- multiple declarations with DEFB,DEFW,DEFI got reference adress of the first outputed byte. That's why with AS80, using multiple DEFB produces a different result than using DEFB with multiple values
- MACRO declaration directive must be used after the macro name
Cool! Thanks!
update v0.72
- ability to generate snapshot v2 (useful with M4Wifi)
short doc
BUILDSNA V2
Hi,
Now I feel dumb, I can not get the program to run. I just see the command prompt window to open in a fraction of a second, not able to read what it says, and that's it.
Bill
Quote from: Bill on 04:14, 27 February 18
Hi,
Now I feel dumb, I can not get the program to run. I just see the command prompt window to open in a fraction of a second, not able to read what it says, and that's it.
Bill
It is a command line tool.
Open a terminal and run
update v0.73
- bugfix in snapshot when using distinct banks instead of gathering them with bankset directive
quick update v0.74
- usage of snapshot directives forces snapshot output
- try to load .asm or .Z80 file if filename given is not found and has no extension
- BREAKPOINT directive may have an additional parameter to set break adress anywhere
- declaring two MACRO with the same name will trigger an error
- bugfix regression of -m option handling
- each REPEAT or WHILE loop export a REPEAT_COUNTER or WHILE_COUNTER variable, locally
update v0.75
- newer and faster expression calculator without limitations of comparisons
- % may be used as modulo (still used for binary values)
- Intel hexa & binary style support
- Binary prefix 0b fixed
- does not export IX and IY anymore in symbol files
- better error messages when calculating expressions
- boolean operators && and ||
- PUSH & POP may have more than one register in parameters
- NOP may be multiplied specifying a number of repetition in parameter
- alias <> for != comparison operator
- filenames are forced to upper case when saved to EDSK
- Infinite loop detection won't go to infinite loop anymore ^_^
As the solver is very different from the previous version, i keep the 0.74 version available, in case of regression
Now i have to work on the documentation, again ;D
Another big update! Thank you!
It's great to have a French manual (mother tongue is always the best). But please also update the English manual if needed (still shows 0.72, not 0.75, but maybe it need no update - I have to find out :-))
Keep the great work going!!! :) :) :)
I have to work on english version too before updating here ;)
Yeah, I know, and making docs and manuals is just no fun. :P But if you come to an end (or close to an end) I would like to make a translation to German language for you. :) Just let me know when "final" stage is in sight :)
update v0.76
- fix solver when using % prefixed binary values close to comparison operator or parenthesis
Both FR & EN doc updated 8)
quick update for maxam compatibility mode users
update v0.77
- even faster expression calculation
- maxam & AS80 comparison operators are back
ultra-light but requested update v0.78
- DEFS can handle multiple repetition schemas
- alias DM & DEFM for DEFB
update v0.79
- != operator is back with new solver :doh:
update v0.80
- bugfix operator > and >=
- bugfix Maxam priorities
update v0.81
- added special maxam priorities for parenthesis and boolean operators
The priority management in maxam compatibility mode is less trivial than it seems to be >:(
Fixes are validated coz 0.81 is working fine for me. 8)
Thanks Roudoudou :-*
Yes, 81 seems to be a good number. Everything stable and well here too. :)
Quote from: GUNHED on 13:32, 06 April 18
Yes, 81 seems to be a good number. Everything stable and well here too. :)
I have another version pending ;D
With 'while 0 bugfix' but nothing really important
Due to my system upgrade (a 6 years old ubuntu LTS to the new Lubuntu beta LTS) i remove many compilation warnings. CLang compilation takes ages but the performance of the executable is noticable (30% faster)
- I added also SL1 alias for SLL
- better infinite loop detection (i mean, safer)
- bugfix while 0 loop (check and disable block)
- repeat until internal counter harmonisation (now they are all starting from value 1)
update v0.83
- NOCODE output must increment current adress in all cases
- new directives DR & DEFR to define REAL values (Amstrad firmware compatible)
Example:
org #8000
call #BBBA ; GRA initialize
ld a,1
call #BC0E ; mode 1
ld a,1
call #BD97 ; deg
ld de,320
ld hl,200
call #BBC9 ; origin 320,200
ld de,180
ld hl,0
call #BBC0 ; move 180,0
ld b,0
circle_trace
push bc
ld hl,angle
ld de,incre
call #BD7C ; angle=angle+incre
ld de,angle
ld hl,tmp
call #BD61 ; tmp=angle
call #BDAF ; tmp=cosinus(tmp)
ld de,rayon
call #BD85 ; tmp=tmp*rayon
call #BD6A ; HL=int(tmp)
call m,fixsign
push hl
ld de,angle
ld hl,tmp
call #BD61 ; tmp=angle
call #BDAC ; tmp=sinus(tmp)
ld de,rayon
call #BD85 ; tmp=tmp*rayon
call #BD6A ; HL=int(tmp)
call m,fixsign
pop de
call #BBF6 ; LINE DE,HL
pop bc
djnz circle_trace
ret
fixsign
ld de,0
ex hl,de
or a
sbc hl,de
ret
rayon defr 180
angle defr 0
incre defr 360/256
tmp defr 0
I just learned (at the Revision, from Offset) that Basic has an integer division, with the symbol \ (or ç on French keyboard). I already reported you that the "accurate" division was a bit problematic in some cases. Do you think something similar could be implemented?
Quote from: Targhan on 08:48, 12 April 18
I just learned (at the Revision, from Offset) that Basic has an integer division, with the symbol \ (or ç on French keyboard). I already reported you that the "accurate" division was a bit problematic in some cases. Do you think something similar could be implemented?
Using INT() must solve the case
You may be interrested also by the floor() function, the result is again different in another way
Example:
a=10
b=2
repeat 10
print a,"/",b," normal=",a/b," int()=",int(a/b)," floor()=",floor(a/b)
b=b+1
rend
Will produce
10.00 / 2.00 normal= 5.00 int()= 5.00 floor()= 5.00
10.00 / 3.00 normal= 3.33 int()= 3.00 floor()= 3.00
10.00 / 4.00 normal= 2.50 int()= 3.00 floor()= 2.00
10.00 / 5.00 normal= 2.00 int()= 2.00 floor()= 2.00
10.00 / 6.00 normal= 1.67 int()= 2.00 floor()= 1.00
10.00 / 7.00 normal= 1.43 int()= 1.00 floor()= 1.00
10.00 / 8.00 normal= 1.25 int()= 1.00 floor()= 1.00
10.00 / 9.00 normal= 1.11 int()= 1.00 floor()= 1.00
10.00 / 10.00 normal= 1.00 int()= 1.00 floor()= 1.00
10.00 / 11.00 normal= 0.91 int()= 1.00 floor()= 0.00
Interesting. But for my use case, I think the shift (>>) will be more explicit, in fact!
update v0.84
- new directives STRUCT and ENDSTRUCT, ENDS to create structures
- fix regression introduced with v0.75 and embedded usage (like Arkos Tracker II does)
Documentation FR updated, EN will follow
Example of structures manipulations
org #1000
label1
struct st1
ch1 defw 0
ch2 defb 0
endstruct
struct st2
ch1 defb 0
ch2 defw 0
endstruct
label2
assert label1==label2 ; declaring a struct does not change code output
assert st1.ch1<st1 ; declaring a struct is not affected by current output adress
assert st1==st2 ; size of both structs is equal (NOT recommended vasm syntax)
assert {sizeof}st1=={sizeof}st2 ; explicit size of
assert st1.ch2!=st2.ch2 ; no confusion between struct with identical fields names
struct metast1
struct st1 sub1 ; imbricated structs
struct st2 sub2
endstruct
label3
assert label3==label2 && label3==label1 ; declaring a struct using struct does not change code output
assert metast1.sub1<metast1.sub2 ; check sub-structs are in order
assert metast1.sub1.ch2<metast1.sub2.ch1 ; check sub-structs are not overlapping
assert {sizeof}metast1.sub1=={sizeof}st1 ; can get sizeof in many ways
assert {sizeof}metast1=={sizeof}st1+{sizeof}st2 ; metast1 struct = struct st1+st2
Ok ok :P ... That's a fact: I am in love :-* :-*
update v0.85
- fix regressions introduced by STRUCT code modifications
- added some checks and error messages
for the record, one of this regression had 1 chance on a billion to occur. Golem13 project wins the ticket! :laugh:
update v0.86
- fix many bugs in label import
- fix multi-nops
- fix automatic extension for primary source
- fix infinite loop when error on reserved keyword in an expression
- shortcuts LD BC/DE/HL,BC/DE/HL (uz80 style)
- UZ80 compatibility option (for new versions of CNG player)
NEW online documentation FR http://www.roudoudou.com/rasm/rasm_fr.html (http://www.roudoudou.com/rasm/rasm_fr.html)
Still working on online ENglish documentation
I'm really enjoying using RASM - thanks roudoudou!
Just wondering, is there a way to have multiple commands on one line?
For example, instead of:
ld a,#33
ld (hl),a
inc l
Is there a way to do something like this?
ld a,#33; ld (hl),a; inc l
[EDIT] I think I found the answer. ;D
ld a,#33:ld (hl),a:inc l
Now THAT is a great feature!
I updated the z80.vim in order to highlight rasm directives
http://www.roudoudou.com/rasm/z80.vim
But i'm still stuck with literal values...
Sometimes no color, sometimes half color (hex values...)
syn match z80Number "\$[\x]\{1,8}"
syn match z80Number "\$"
syn match z80Number "0x[\x]\{1,8}"
syn match z80Number "0b[01]\{1,32}"
syn match z80Number "#[\x]\{1,8}"
syn match z80Number "%[01]\{1,32}"
syn match z80Number "@[\o]\+"
syn match z80Number "[01]\{1,32}b"
syn match z80Number "[\x]\{1,8}h"
syn match z80Number "[0-9\.]\+"
I very nice feature for the C developper could be the possibility to generate a Library compatible SDCC.
Of course i have not idea how difficult could be the task :P
Quote from: Arnaud on 08:01, 06 May 18
I very nice feature for the C developper could be the possibility to generate a Library compatible SDCC.
Of course i have not idea how difficult could be the task :P
I guess i have to find the .rel format description?
Quote from: roudoudou on 08:09, 06 May 18
I guess i have to find the .rel format description?
There's a doc about library in SDCC / SDASsembly (sdcc/src/sdas/doc)
Quick question about using ORG...
I've got a bunch of code that refers to a jump table.
A trivial example:
ORG #9000
LD HL,jumptable
; do some stuff
RET
jumptable:
defw row1,row2,row3,row4
defw row5,row6,row7,row8
I can't figure out how to put the jump table at a specific memory address.
When I try (by putting ORG #9800, for example), I get all sorts of unexpected behaviour.
When I don't have ORG before the jump table, the program behaves correctly.
Is there a way to put the jump table into a specific memory address?
Thanks.
Quote from: ervin on 01:09, 11 May 18
Quick question about using ORG...
I've got a bunch of code that refers to a jump table.
A trivial example:
ORG #9000
LD HL,jumptable
; do some stuff
RET
jumptable:
defw row1,row2,row3,row4
defw row5,row6,row7,row8
I can't figure out how to put the jump table at a specific memory address.
When I try (by putting ORG #9800, for example), I get all sorts of unexpected behaviour.
When I don't have ORG before the jump table, the program behaves correctly.
Is there a way to put the jump table into a specific memory address?
Thanks.
Could you be more specific?
org #9000
ld hl,jumptable
org #9800
jumptable
defw row1,row2,row3
org #A000
row1 nop
row2 nop
row3 nop
is assembled correctly so i guess the error is elsewhere
#21 #00 #98
...many zeroes...
#00 #A0 #01 #A0 #02 #A0
for a total of 4099 bytes
Quote from: roudoudou on 07:57, 11 May 18
Could you be more specific?
org #9000
ld hl,jumptable
org #9800
jumptable
defw row1,row2,row3
org #A000
row1 nop
row2 nop
row3 nop
is assembled correctly so i guess the error is elsewhere
#21 #00 #98
...many zeroes...
#00 #A0 #01 #A0 #02 #A0
for a total of 4099 bytes
The simplified example I gave was just to demonstrate the code structure.
In my program where I'm moving a large sprite around the screen, the sprite is drawn very quickly, when I don't have the ORG before the jumptable.
When I
do have the ORG before the jumptable, the program slows down tremendously, although I think it is the screen rendering that is being slowed down instead of the sprite.
Actually maybe the ORG #9800 is clashing with something in my rendering code... I don't think it is, but I'll check it out.
Yes, indeed it was my silly mistake.
I was overwriting other data.
My apologies for the confusion.
RASM looks awesome... but it doesnt run in my old PC (win xp)
it says "rasm.exe is not a valid win32 application" >:(
sorry perhaps I am old and lame...
Quote from: fgbrain on 09:05, 14 May 18
RASM looks awesome... but it doesnt run in my old PC (win xp)
it says "rasm.exe is not a valid win32 application" >:(
sorry perhaps I am old and lame...
I will try to compile a 32 bits version (if i find the correct compiler option)
Quote from: fgbrain on 09:05, 14 May 18
RASM looks awesome... but it doesnt run in my old PC (win xp)
it says "rasm.exe is not a valid win32 application" >:(
I added the archive rasm_v086_exewin32.zip (http://www.cpcwiki.eu/forum/programming/rasm-z80-assembler-in-beta/?action=dlattach;attach=25373)in the first post
I am sorry to say that this new exe doesn't work as well...
Runs in window and closes immediately!!
Quote from: fgbrain on 19:15, 14 May 18
I am sorry to say that this new exe doesn't work as well...
Runs in window and closes immediately!!
It's a command line tool, so open a terminal to run it
And as Rasm is the fastest assembler ever made, i'm happy to see the windows closes "immediately" even on an old XP machine ;D
Quote from: roudoudou on 19:19, 14 May 18
And as Rasm is the fastest assembler ever made, i'm happy to see the windows closes "immediately" even on an old XP machine ;D
It's lightning fast indeed, big pleasure to use, thanks!
Hi
For the time being, Rasm manage local labels inside macro & loops
As indicated by his name, local means local. That kind of label cannot be exported/used outside the macros or the loops
example:
repeat 10
add hl,bc
jr c,@verflow
dec hl
@verflowrend
As suggested by Krusty, it could be cool to have another kind of local labels. I think a cool name could be 'proximity labels'
Instead of macro or loops, the scope of operation will be delimited by global labels (default labels are globals)
example:routin1
ld b,5
@proximity
djnz @proximityret
routin2
ld b,5
@proximitydjnz @proximityret
This kind of labels may be used outside the scope, using the previous global label as prefix
ld hl,routin1.proximity
ld de,routin2.proximity
The things is local labels and proximity labels will share the '@' prefix, leading (i think) to confusion
I may use the dot '.' prefix for proximity labels, but only in pure Rasm mode (not Maxam compatible) as the dot was a f*cking sh*tty method to declare labels
So i'm not yet decided on the right syntax (but using the dot make sense)
Can you fix the return carriages of your code snippets please? I don't understand exactly how this works! Thanks.
Quote from: Targhan on 21:52, 18 June 18
Can you fix the return carriages of your code snippets please? I don't understand exactly how this works! Thanks.
sorry, always this shitty WYSI(not)WYG editor >:(
I think the dot notation makes more sense because:
- other assemblers I used do that - more importantly, the semantic is not the same; so there is no reason that the symbol to use is the same
@targhan I'm pretty sure sjasmplus has local labels
The dot makes sense. However... what would be the use of such "proximity" label?
@krusty_benediction yes, SJAsmplus manages local labels.
The purpose of proximity labels is to offer an entry point everywhere, without having unicity of labels
You can use a label .loop almost everywhere when you need it (but not directly after another .loop label) :)
BUT, if you need to jump to a proximity label out of the scope, just add the global reference -> routine1.loop, routine2.loop, ...
Anyway, that feature is a feature, there is no obligation to use it.
Hmm, I'm note sure I understand, but is the following correct:
MySubCode:
ld a,5
.loop
dec a
jr nz, .loop --> it will jump one line above.
ret
MySubCode2:
ld b,10
.loop
djnz .loop --> it will jump one line above, NOT to the MySubCode.loop
ret
Right?
yes. This is what I'm doing since years with vasm and asjamsplus
I use normal label as function (i.e. similar to a function in C language) name and local labels as branches inside the function (.i.e. similar to a label in C language)
Quote from: Targhan on 13:48, 19 June 18Hmm, I'm note sure I understand, but is the following correct:
MySubCode:
ld a,5
.loop
dec a
jr nz, .loop --> it will jump one line above.
ret
MySubCode2:
ld b,10
.loop
djnz .loop --> it will jump one line above, NOT to the MySubCode.loop
ret
Right?
Not a bad idea indeed!
huge update, documentation is not finished yet (and the english version is still 10 versions late...)
update v0.87
- new proximity labels
- rasm is able to use variables inside label names
- INCBIN directive enhanced for WAV import as a CPC sample or DMA list
- REPEAT directive may export internal counter to a variable
- new directive IFUSED & IFNUSED
- new math operator ! for NOT
- new math function PSGVALUE
- rasm return 1 to shell when there is error(s)
- new options to export dependencies (makefile style)
- new option to define variable(s) from command line
- new option for extended error messages
- bugfix cases during preprocessing
- bugfix tags PAGE & PAGESET
- new autotests embedded in Rasm in order to reduce regressions
Quote from: roudoudou on 08:37, 24 June 18
(and the english version is still 10 versions late...)
Please catch up, before you forget everything ;) :) :) :)
update v0.89, many bugfixes due to recent evolutions
- bugfix dependencies export
- bugfix in preprocessor
- simplify path of dependencies when possible
- enhanced ASSERT may PRINT additional parameters
update v0.90
- PROTECT directive does not increase automatic binary size anymore
- bugfix memory leak with proximity labels
- proximity label properties also for alias EQU
- label declaration may use formula (with tags), but only declaration for the moment
still working on doc. French doc partially updated and onlineEnglish online documentation done at 75%
doc updated :)
QuoteDocumentation FR http://www.roudoudou.com/rasm/rasm_fr.html (http://www.roudoudou.com/rasm/rasm_fr.html)
Documentation EN http://www.roudoudou.com/rasm/rasm_en.html (http://www.roudoudou.com/rasm/rasm_en.html)
Actually for EN this link works:
http://www.roudoudou.com/rasm/rasm_en.html
Quote from: GUNHED on 09:27, 28 June 18
Actually for EN this link works:
http://www.roudoudou.com/rasm/rasm_en.html (http://www.roudoudou.com/rasm/rasm_en.html)
Thanks! Again this shitty editor :'( I fixed my postS
@roudoudou (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1714) :
RASM says during assembling that after e.g. LD BC,#FF63
and an OUT (C),A
it is truncating the value #FF63 to #63. Does it really truncate it?
Quote from: HAL 6128 on 18:36, 07 July 18
@roudoudou (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1714) :
RASM says during assembling that after e.g. LD BC,#FF63
and an OUT (C),A
it is truncating the value #FF63 to #63. Does it really truncate it?
Quotesorry i cannot reproduce what you say with ld bc,#FF63 and out (c),a
Quotemust be another line
Quotehave you some DB/DEFB around?
Hmm, sorry. I found the error I made.
I've defined a variable:
VALUE EQU #FF63
...
LD A,0
LD BC,#FF63
OUT (VALUE),A
I had forgot to rewrite the out command.
update v0.91
- bugfix school case with crunched block
- bugfix proximity labels when using loops or macros
- bugfix imbricated IFUSED/IFNUSED
- new directive FAIL will print a message before exiting with an error flag
- label usage may use formula
- escaped codes support in strings (disregarding the current charset)
- PRINT directive may compute formula in strings when using curly brackets
- RUN directive may set the gate array configuration for snapshots
- generated label with negative index will trigger an error
- overriding an alias with a variable will trigger an error
- overriding a variable with an alias will trigger an error
- missing ENDIF at the end of the source will trigger an error
Rasm forever ! May the french soccer team win tonight !
Did not see the match, i was busy fixing PAGE tag -> v0.92 update ;D
Hi!
In RASM there is this code example:
ld (iy+1),PDATE
ld (iy+2),PDATE>>8
PDATE equ 1234
How would this be written in Maxam (I need this for quick testing)
replace >>8 by /256
Note: In rasm mode /256 will round upper, in maxam mode this will truncate and may lead to another result
Thanks, I thought about /256. Maxam does it like RASM. But...
ld (iy),variable_of_16_bit
What does it do in RASM? Does it only write the lower 8 bits? Maxam produces an error.
Sorry for bugging, but in the example before, it would write the hi-byte first, and then the low-byte. Shouldn't it the other way around?
RASM is really full of new features, lot's of stuff to learn ;-)
Quote from: GUNHED on 00:27, 11 July 18
Thanks, I thought about /256. Maxam does it like RASM. But...
ld (iy),variable_of_16_bit
What does it do in RASM? Does it only write the lower 8 bits? Maxam produces an error.
Sorry for bugging, but in the example before, it would write the hi-byte first, and then the low-byte. Shouldn't it the other way around?
RASM is really full of new features, lot's of stuff to learn ;-)
with rasm you can do
ld (iy+0),lo(variable_of_16_bit)
ld (iy+1),hi(variable_of_16_bit)
or
ld (iy+0),variable_of_16_bit&#FF
ld (iy+1),variable_of_16_bit>>8
there is no other shortcut but you can also do a macro :)
macro LDIY16 valuetoput
ld (iy+0),lo({valuetoput})
ld (iy+1),hi({valuetoput})
endm
Cool! Thanks!
update v0.93
- bugfix RUN gate array configuration
- overriding an alias with a label will trigger an error
- PRINT directive may use escaped chars in strings
- tags BANK,PAGE,PAGESET may be used with current adress $
A bug may still occur with proximity labels mixing macro, generated names (but i cannot reproduce it)
update v0.94
- bugfix using macro parameter inside print quote
- bugfix multiple memory leak with tag replacement
- bugfix command line side effect with wrong option
- better hack in expression calculator for expression beginning with negative value
- better equality processing in expression calculator
exewin32 does not have all the fix, will be available monday since i need a 32 bits compiler i do not have at home
update v0.95
- allow spaces in tags inside strings with PRINT directive
- display warning if you try to export symbols or breakpoints with snapshot version 2
- proximity label beginning with BRK will generate an exportable breakpoint
- new enhanced LD instructions documented here http://www.roudoudou.com/rasm/rasm_en.html#Instructions
For those using Visual Studio Code as Integrated Development Environment for the Amstrad CPC, you can install the "z80 macro assembler" extension that provides syntaxic coloration of code and some snippets for rasm. On my side it has completely replaced vim and its tailored extension. Syntax error analysis is only the missing thing for me
QuoteFor those using Visual Studio Code as Integrated Development Environment for the Amstrad CPC, you can install the "z80 macro assembler"
Looks interesting. But the "Goto definition" does not seem to look outside the current file. And how do you create a build task?
A javascript master like you may be able to fix this goto issue by proposing a patch to its author ;)
On my side I use Makefiles in a Dockerized environment to manage all my stuff, so my build task is simply a Makefile call. So my minimum tasks.json file looks like taht
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Build",
"type": "shell",
"command": "./bootstrap.sh make",
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "CPC",
"type": "shell",
"command": "./bootstrap.sh make run_on_cpc",
"group": {
"kind": "run",
"isDefault": false
}
}
]
}
Javascript master? Well, that's one language I certainly don't master :). Thanks for the script, I'll check it out! But right now, the solution isn't as good as what I already have!
update v0.96
- bugfix memory leak in tag translation with PRINT directive
- bugfix negative offset with INCBIN
- bugfix autotests memory handling
- added include path in command line
- doc updated
msdos version does not include all v96 update (monday)
Quote from: Targhan on 10:46, 24 July 18
Looks interesting. But the "Goto definition" does not seem to look outside the current file. And how do you create a build task?
are you sure about the goto thing ? Just be able to jump in another (but opened) file
update v0.97
- bugfix conditionnal code inhibition with macro declaration
- better alias infinite recursivity detection
So I finally decided to give a try to Rasm.. so far so good :P
The transition was smooth (coming after years of dev under WinAPE). I was used to & for hexadecimal values, had to spend few hours before getting used to # notation.
What I am appreciating so far:
- the doc is awesome (I started with the English version but finally ended with the French one, my eyes were bleeding too much ;-).
- the << >> & parentheses etc. All those stuff works as expected. Under WinAPE, I (sometimes) had to fight with several constants to get same result
- the print vs. fail commands is good catch! I use fail in my macros to simulate an Assert at compile-time, very practical
- WinAPE was often kind of confused when dealing with macros, rasm does a much better job here to handle (report) errors
- looks mature in current state!
Good job Roudoudou.
Yes, this is definitively the most promising assembler.
However, it is not yet enough mature (I regularly hit bugs), but is going to be as Roudoudou is really reactive when we catch bugs (and is not closed to suggestions).
I have not yet totally switch from vasm to rasm.
Hi @roudoudou (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1714)
the code next shows me an error message "cannot use register 6<>A in this context". How can I solve this?
Kind regards,
HAL6128
macro setreg val
if {val}<>a
ld a,{val}
endif
push bc
ld bc,PORT ;PORT to be defined
out (c),a
pop bc
endm
org #9000
setreg 6
ret
conditional directives do not know the content of registers, so this is a correct behavior for any assembler
maybe you should add a second argument to your macro that contains the current value of A but YOU have to know it when calling it
This is a code snipped from 1990. Compiled with Z80ASM which looks like this. Maybe I misinterpreted it?
macro setreg val
ifdif val,a
ld a,val
endif
.. endm
org #9000
setreg 6
ret
With a (partial) integrated code simulator this may work but not in all cases (example: register a taking his previous value from memory)
Golem is using macros and variables like this, with a variable REG_A mirroring register A, so when he does LD A,n he's doing also REG_A=n
This can work with very linear code
update v0.98
- bugfix with snapshot v2 memory size detection
- new optional parameter to get file size when load and crunch on the fly
- new option to remove warnings
- new fake instructions RR,RL,SRL,SRA,SLL,SLA with 16 bits (BC,DE,HL) registers
- preprocessing does not allow empty parameter to avoid confusion
- extended error may suggest a name if a variable/label/alias looks similar to a 'not found' value
update v0.99
- new directive UNDEF
- bugfix memory leaks
- bugfix calculations with functions immediatly followed by two or more opened parenthesis
Quote from: roudoudou on 14:13, 16 August 18
update v0.99
- new directive UNDEF
- bugfix memory leaks
- bugfix calculations with functions immediatly followed by two or more opened parenthesis
The v1.0 is near :D
back from holidays, small update
update v0.100
- bugfix crash with zeroed output file
- bugfix moar memory leaks
update v0.101
- warn if no byte is written to a snapshot
- warn if RUN directive was already used
- bugfix calculation error cases
- bugfix maxam AND/OR/XOR/MOD operator (regression of v0.89)
- UNDEF does not care anymore about variable existence
- better error management with macro and wrong number of parameters
Siko is working on a new FR/ENG documentation, please be patient 8)
update v0.102
- bugfix 'BREAKPOINT <adress>' export
- bugfix default limit of 65535
- bugfix limit autotest
- bugfix path simplification for dependencies export
- bugfix memory leak when using (VOID) with macro
- new math function to get a random value
Hi,
Very impressive work with RASM ;)
I have noticed an error in documentation
I think that it should be
- Merkle tree
and not
- Merkel tree.
Don't you think ?
Bye.
Quote from: gryken on 11:31, 29 November 18
Hi,
Very impressive work with RASM ;)
I have noticed an error in documentation
I think that it should be
- Merkle tree
and not
- Merkel tree.
Don't you think ?
Bye.
Thanks
The documentation will be updated soon
Hello,I mainly use rasm for my current handwritten code, but I have also written an assembler for my computer generated code (of course, wh'ne I'll have the courage to implement all mnemonics it will replace rasm in my workflow ;)).I have played today with some directives that could be also usefull with rasm.
Here is a test code that validated the approach
ld a, screen_height
player_line_loop
stableticker start effectduration ; Start to count nops
ex af, af'
pop hl ; 0 1
xor a : out (c), a : out (c), l
inc a : out (c), a : out (c), h
repeat 7
pop hl ; 2 3 to 14 15
inc a : out (c), a : out (c), l
inc a : out (c), a : out (c), h
endr
ex af, af'
dec a
stableticker stop
defs 64*3 - effectduration - (1 + duration(jr nz, player_line_loop))
jr nz, player_line_loop
There is a simple routine that must be played at a certain frequency. Usually we manually compute the number of nops it takes in order to add filling instructions to have the right duration.Its booooring, especially when you forget the timing. So I have added 2 directives to delegate the job to the assembler:- stableticker that counts the number of nops and store them in a variable- duration that can be used in any expression and provide the number of nops of its instruction
Of course there is a limitation with the conditional opcodes having different durations. In my implementation I select the shortest one (that's why I add 1).
This can be generalized to other kind of functions like opcode(mnemonic) that would return the 16bits value of any 8bits/16bits instruction. It will be probalby my homework of tomorrow
@roudoudou (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1714) what do you think about implementing them (or more egonomics versions) ?
Quote from: krusty_benediction on 00:19, 28 December 18...
This would be cool!
But if you start ticker with a variable name, why not stopping ticker also with a variable name?
Then you may start as many tickers as you want?
2 resaons :
- I did that late, it is more difficult to make good choices ;)
- I only though about nested calls and not overlapping calls. But yes to provide an optional argument to stop allows to handle all cases
BTW tell us more about your assembler :P
It is currently only a library ;not an executable able to assemble any file.I have not implemented all the mnemonics and directives. Only the things I needed to advance.
I have a parser that generates tokens from a source code. These same tokens can be generated (to noyt code the effect myseld) or manipulated (to optimize or inject specific code at specific place/moment) by my other demotools.
And I have the assembler that transform these tokens in a stream of bytes. My other tools inject them in a snapshot.
So barely useable by someone else ;) If you are curious, everything is there: https://github.com/cpcsdk/rust.cpclib/tree/master/src/assembler (https://github.com/cpcsdk/rust.cpclib/tree/master/src/assembler)
Quote from: krusty_benediction on 00:19, 28 December 18
There is a simple routine that must be played at a certain frequency. Usually we manually compute the number of nops it takes in order to add filling instructions to have the right duration.Its booooring, especially when you forget the timing. So I have added 2 directives to delegate the job to the assembler:- stableticker that counts the number of nops and store them in a variable- duration that can be used in any expression and provide the number of nops of its instruction
I've done the ticker ;)
update v0.105- bugfix wrong error with operator+non decimal negative value
- do not allow CALL (IX) or CALL (IY) syntax
- added comments begining with //
- added SIZEOF support for fields of structures
- new directive TICKER to count instruction duration
New French and English documentation by Siko (Stéphane S.) in the first post 8)
super manuel. Il y a quelques typos avec {sizeof}
update v0.106
- multi-line comments with /* */
update v0.107
- colored output with Unix terminal- trigger error if a (VOID) arg is used with a macro which has parameter(s)
- added Vasm syntax ENDREP and ENDREPEAT to end a REPEAT block
- enforce zero result when there is an error in a calculation
- new directives NOEXPORT/ENOEXPORT to disable/enable on demand symbol export
Thanks @roudoudou (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1714) !!
Really cool progress. Would it also possible to have (oldschool) .PHASE and .DEPHASE directives , like in the M80 assembler?
Quote from: HAL 6128 on 20:20, 16 January 19
Really cool progress. Would it also possible to have (oldschool) .PHASE and .DEPHASE directives , like in the M80 assembler?
I may add it in the next release, but you can do it already with macros ;D
macro phase adr
org {adr},$
mend
macro dephase
org $
mend
Very helpful, thanks!
What would you think the best way to emulate the MAP feature of SJAsmPlus:
MAP 8
Label # 2 ; Label=8
Kip # 3 ; Kip=10
Kop # ; Kop=13
Kop2 # 1 ; Kop2=13
I would like to avoid doing this:
Start equ #4000
Stuff1 equ Start + 0
Stuff2 equ Start + 1
Stuff3 equ Start + 3
...
Ideally, I'd like to declare the size of each item:
Start <struct> #4000
stuff1 <declare byte> ;stuff1=#4000
stuff2 <declare word> ;stuff2=#4001
stuff3 <declare word> ;stuff3=#4003
...
you have the STRUCT directive
struct targhan
stuff1 defs 1
stuff2 defs 4
stuff3 defs 2
stuff4
endstruct
nocode
org #4000
struct targhan m4
code
; m4.stuff1=#4000
; m4.stuff2=#4001
; m4.stuff3=#4005
; m4.stuff4=#4007
Ahhhh good. I knew about Struct, but forgot about the "nocode" directive. Thanks!!
I think it is not documented; I discovered it in the post
Quote from: krusty_benediction on 13:35, 23 January 19
I think it is not documented; I discovered it in the post
These directives are obsolete. They were used in Maxam in order to create kind of structures.
I realize now that we can have a more modern usage :D
Well, IMHO nocode is really useful, every assembler should understand it. I work with Z80, I have my style and I don't need anything modern. ;D ;) :)
RASM is great, and Maxam compatibility is (for me) the most important thing. :)
It works, but makes the code a bit complicated :). The ORG change is problematic, so I have to save it and restore it then:
SaveOrg = $
...
org SaveOrg
But it works :).
Quote from: Targhan on 19:26, 23 January 19
It works, but makes the code a bit complicated :) . The ORG change is problematic, so I have to save it and restore it then:
SaveOrg = $
...
org SaveOrg
But it works :) .
I will read again the MAXAM doc about the behaviour of CODE/NOCODE
Assembling in RAM: NOCODE will stop putting bytes into RAM, when using CODE the bytes are again written in RAM, at the right address.
Assembling to disc: NOCODE stops writing bytes to the output file (binary), then the CODE command will again write the bytes to the file, but the gap in between will NOT be filles with zeros.
So after NOCODE and CODE the binary output file will have a gap and the bytes written after CODE are to early in the file.
Usage of NOCODE: Very nice when testing, but you don't want to write to RAM or file.
Thanks Gunhed so the actual NOCODE is legacy but i may add an option to CODE to get the previous $
CODE NOGAP or something like this?
Advice needed. The Arkos Tracker players have duplicated code (for each channel). I'd like to avoid this, but this is tricky. Maybe one of you can enlighten me on how to improve this.
I know I can use macro and local labels.
MACRO ManageNote
ld hl,(@stuff + 1)
@stuff ld de,#4000
ENDM
ManageNote ;For channel 1
ManageNote ;For channel 2
ManageNote ;For channel 3
The problem is, I would like to have these macros to address labels from the related channel.
MACRO ManageTrack
ld hl,(@stuff + 1) ;From the macro above!!
ld de,12
add hl,de
ENDM
ManageTrack ;For channel 1
ManageTrack ;For channel 2
ManageTrack ;For channel 3
How is it possible? I should be able to generate labels, maybe from placeholder and parameters in the macro, but it probably won't work...
... After testing... YES IT WORKS!! Damn, this is great!
MACRO test chan
defb {chan}
stuff{chan} ld a,0
ENDM
test 1 ; This generated a "stuff1" label!
test 2 ; This generated a "stuff2" label!
This is amazing!! Well done Roudoudou!! This is crazy stuff. Ok, I guess I have found my solution, but if anyone want to add it 2 cents, thanks :).
update v0.108
- allow var name beginning with '_'
- CODE directive may retrieve last outputed byte adress
org #100
nocode
nop
code
print $ ; #101
org #200
nocode
nop
code skip
print $ ; #200
Hi roudoudou,
a question regarding the 'save' directive: what are the options for overwriting an existing file on a DSK?
Quote from: HAL 6128 on 15:17, 28 January 19
Hi roudoudou,
a question regarding the 'save' directive: what are the options for overwriting an existing file on a DSK?
this is the
-eo option with the command line
Here is another directive suggestion for rasm LOCOMOTIVE/ENDLOCOMOTIVE in order to generate basic bootstrap code that launches the binary file.I've just validated the concept with my prototype assembler.
Here is the sample file I have produced (and I have enclosed the generated file):
LOCOMOTIVE code
10 ' Hello world
20 call {code}
ENDLOCOMOTIVE
code
di
ld hl, 0xc9fb
ld (0x38), hl
ei
ld bc, 0x7f10 : out (c), c
ld a, 0x40 : out (c), a
jp $
The assembler generates the tokens of the basic program.One of the instruction is call {code} where {code} is replaced by the value of the label {code} in the assembly code. So any {XXX} is replaced by the value of XXX in the symbole table if XXX is provided as an argument of LOCOMOTIVE
It is probalby interesting to add specific comments that contain tags asking to hide some basic lines (for a demo line 20 should be hidden).
would be such a huuuuuuuuuuuge work
ps: PDF documentation updated!
Quote from: HAL 6128 on 15:17, 28 January 19
Hi roudoudou,
a question regarding the 'save' directive: what are the options for overwriting an existing file on a DSK?
I found an issue with file overwriting and DSK update
You should delete the dsk meanwhile i fix this
update v0.109
- bugfix crash when trying to save with a negative size
- bugfix crash case with macro and wrong parameter number
- bugfix EDSK update
- IFDEF/IFNDEF now scans for macro names
- TZX/CDT output support (not working)
- RUN directive may use unknown var as parameter
- embedded Rasm may return info struct about errors and symbols
There is more different files to download:
- msdos version
- windows 32bits executable
- windows 64bits executable (20% faster than 32bits version)
- sources
update v0.110
- allow numeric expression beginning with +
- bugfix uninitialized memory reads and memory leaks with embedded Rasm
update v0.111
- error management code cleanup
- new options with directive INCBIN for wav import
- allow EDSK with invalid track sector size or supernumerary tracks if sectors are DATA compliant
- bugfix confusion between generated global labels and local labels for export
- bugfix EQU with generated names AND curly brackets formulas inside a loop
- bugfix invalid REPEAT values will increment the error counter
Everything 111 now! Thanks for the comprehensive update, that was for sure lot's of work! Great! :)
update v0.112
- bugfix single NOP wasn't increment nop counter ^_^
- bugfix NOP count with ADD/SUB/XOR/AND/CP (IX+n)/(IY+n)
- bugfix in WAV import
And new PDF for documentation ;)
update v0.113
- trigger an error when dynamic LZ section cannot crunch
- bugfix when trying to crunch an empty section
- dynamic debug options removed
- snapshot & cartridge summary by default
- embedded rasm export all labels and EQU in the info struct
- new math function CEIL
- rasm may handle generated name with INCBIN directive
update v0114 (summer release!)
- new INCBIN options: REMAP, REVERT, VTILES
- new command line option "-oa" to mimic inputname for binary output
- try some file extensions if the input file is not found
- new alias EXA for EX AF,AF'
When I read your "summer update" 's changelog - I conclude your assembler is more than mature and you don't know what to add to it now. :)
Yeah, maybe some CDT output, a future SNA v4 (memory+roms+cartridge+floppy)
Maybe it's time to work on something else (finish my bubble game (need GFX polish and music)! Work on a new demo, ...)
roudoudou, first of all thank you for this assembler.
It's one of few which handles forward references without any issues.
Though I'm not a CPC guy (ZX here), but I'm actively using it.
For some time (I don't remember since which version) rasm occasionally crashes in "preprocessing" (I guess) stage. It might be related to uninitialized variables due to this "irregular" nature. I couldn't isolate which exactly code causes this crash, since I use it for pretty big project, and it would take alot of time to figure this out.
It would be nice to have some kind of "verbose" assembling to ease this task.
P.S.: I just found, that 64bit versions actually doesn't crash, it seems it's the 32bit version issue.
Quote from: Volutar on 10:32, 03 July 19
Though I'm not a CPC guy (ZX here), but I'm actively using it.
I'm very happy to read ZX people use Rasm! Let me know if you want some TZX export or anything else! (i will need documentation obviously)
Quote from: Volutar on 10:32, 03 July 19For some time (I don't remember since which version) rasm occasionally crashes in "preprocessing" (I guess) stage. It might be related to uninitialized variables due to this "irregular" nature. I couldn't isolate which exactly code causes this crash, since I use it for pretty big project, and it would take alot of time to figure this out.
P.S.: I just found, that 64bit versions actually doesn't crash, it seems it's the 32bit version issue.
If sources are not secret, you may send the whole package to me
Or i may send you a version with debug informations in order to use Visual Studio debuger
Or i may send you a version with many output traces during prepro+assembly (very heavy debuging)
update v0.115
- bugfix preprocessing with multi-line comments
- bugfix unrecognized % for modulo
- new banking BUILDZX directive for ZX Spectrum usage
and a new option to export symbols for ZX emulators with bank:label informations
Hello,rasm is able to define prototype of structures and to instantiate them.However, although it does not raise an error, it seems it is not possible to define value to the field at their instantiation.Is it possible to add such ability ?
For example, st1 of the documentation could be instanciated as :struct st1 mylabel 1, 2in order to generatemylabel.ch1 dw 1.ch2 dw 2
and for metast1:struct metast1 mylabel2 1,2,3,4in order to generatemylabe2.pr1.ch1 dw 1.pr1.ch2 dw 3
.pr2.ch2 dw 4
oldstyle syntax of vasm allows such thing. It is really usefull
thx
I guess it's possible
Quote from: roudoudou on 18:34, 17 August 19
I guess it's possible
Great, lI'm ooking forward for such improvment
Heyo, going to try and use this assembler considering that it has documentation that's pretty straightforward and simple in terms of telling you how to assemble. Thanks for your work! I'll try and give an update afterwards, since if a beginner like me can use it, then, in my opinion, it's been designed well.
Hi
there is a big regression in DSK support since 0.112
many fixes are coming soon but i'm still working on it
sorry for the delay, i moved house twice this year and i'm soooooo tired ;D
++
update v0.116
- bugfix infinite loop when first file is not found
- bugfix using prefix with generated label name
- bugfix default max limit (no moar 65535)
- bugfix eDSK generation with interlaced sectors (wrong since 0.112)
- bugfix snapshot with moar than 192K of extended RAM
- snapshot now use PPI control value to 0x82 as default
- struct definition allow DEFB,DEFW,DEFI,DEFR to be used without value
- struct usage may use default values of the struct definition
- struct usage allow inline values for each field
- allow use CP with non implicit A register
- allow proximity label without previous global label (mostly for heritage sources)
- more flexibility with DEFS value
- new math functions GET_R, GET_G/GET_V, GET_B to manage amstrad Plus colors
- new math functions SET_R, SET_G/SET_V, SET_B to manage amstrad Plus colors
- new symbol export option to export one file per memory space
- MX chunk support for up to 4M snapshot with ACE emulator
- BANK, PAGE and PAGESET enhancement for 4M snapshot support (now return 16 bits gate array value)
Thank you, I will test this version on my project tonight... and come back to you if necessary!
update v0.117
- new spectrum option HOBETA for SAVE directive
- new snapshot 48K output when using spectrum mode
- bugfix error message when trying to export in symbol file an invalid (but not used) EQU
- bugfix PAGE,PAGESET when used with generated label names and defered computation
- bugfix automatic uppercase+remove spaces in formulas for generated names with INCBIN
- bugfix using negative size with INCBIN (will compute filesize + negative size)
128K snapshot for spectrum next timedocumentation soon ;)
Quote from: roudoudou on 10:42, 22 November 19
update v0.117
- new spectrum option HOBETA for SAVE directive
- new snapshot 48K output when using spectrum mode
- bugfix error message when trying to export in symbol file an invalid (but not used) EQU
- bugfix PAGE,PAGESET when used with generated label names and defered computation
- bugfix automatic uppercase+remove spaces in formulas for generated names with INCBIN
- bugfix using negative size with INCBIN (will compute filesize + negative size)
128K snapshot for spectrum next timedocumentation soon ;)
Just compiled v0.117 and when you run it 'rasm -v' it still says its 0.116
Am i doing something silly or did some one forget to roll the version number :laugh:
cheers
shifters
Quote from: shifters74 on 11:19, 14 December 19
Just compiled v0.117 and when you run it 'rasm -v' it still says its 0.116
Am i doing something silly or did some one forget to roll the version number :laugh:
cheers
shifters
i forget ;)
just edit the version in the very first lines
Quote from: roudoudou on 13:21, 14 December 19
i forget ;)
just edit the version in the very first lines
or just make a new release with the version number fix as the only fix :P
I thought the same... ;D
update v0.118
- bugfix using variables for size/offset with SAVE directive
- bugfix using variables for size/offset in a loop with INCBIN directive
- bugfix error message causing core dump (when doing macro inception)
- new option to enforce void usage with macro without parameter
- new option for INCBIN to interlace+zigzag tiles
update v0.119
- bugfix ASSERT with extra-parameters
- local labels are also reference for proximity label inside their respective scope
- struct may be indexed (work in progress concerning init and filler)
- RUN directive also set execution adress for SAVE directive and may be used multiple times
- new option -wu in order to make warnings for every unused var, alias or label
This great assembler runs with MS-DOS? Oh, then ... it would be really great to have a CP/M Plus version too. :) ;D :)
Quote from: roudoudou on 08:58, 22 February 17
update v0.119
* rasm_v0119_srcbis.zip (185.86 kB - downloaded 10 times.)
Hey, RASM is open-source (MIT expat license).
Great! This means it can be compiled on more exotic architectures (use it on ARM machines like Pi, smartphone, etc).
I might incorporate it in https://github.com/cpcitor/cpc-dev-tool-chain
Wow, one 600kbytes / 17klines source code file. Compiled in 7 seconds on my fast i7, mkay.
Other libraries "repacked" in one big .h file.
Roudoudou, what is the purpose of that? Simplifying compilation steps?
Notice that usual one-file libraries do have a common pattern to make them compatible with multi-file source:
after the interface declaration (normal .h structure) append the implementation (normally in several .c) enclosed with
#ifdef LIB_FOO_IMPLEMENTATION / #ENDIF . With this you can #include the single-file-lib from several source, and only one will do
#define LIB_FOO_IMPLEMENTATION before.
For one example, miniaudio used in RetroVirtualMachine and to which I contributed a little, see https://github.com/dr-soft/miniaudio#user-content-building
Anyway, thanks a lot for sharing the source!
Back to my question, what is the purpose of repacking the external dependencies?
Quote from: cpcitor on 16:18, 12 January 20
Hey, RASM is open-source (MIT expat license).
Great! This means it can be compiled on more exotic architectures (use it on ARM machines like Pi, smartphone, etc).
I might incorporate it in https://github.com/cpcitor/cpc-dev-tool-chain (https://github.com/cpcitor/cpc-dev-tool-chain)
Wow, one 600kbytes / 17klines source code file. Compiled in 7 seconds on my fast i7, mkay.
Back to my question, what is the purpose of repacking the external dependencies?
Hi
Rasm is already running on PowerPC and MorphOS (thanks Philippe R.) so i guess it should run properly on ARM (use the hidden option -autotest ;D )
The non-standard package is for:
- execution speed
- easy for me to navigate in the source code
- easy to compile, avoid external dependencies version problems
- the project was not supposed to be public (just wanted to finish my demo on time)
Hey Roudoudou! :)
Quote from: roudoudou on 08:58, 22 February 17
update v0.119
Thanks again a lot for making the source available under a FOSS license!
ContextI'm starting to integrate it in cpc-dev-tool-chain. Currently, my local branch of cpc-dev-tool-chain can automatically fetch Rasm, compile it and add it to PATH.
Thanks to basing everything on source code, this should work on many architectures and OS.
(Some day I will probably offer complete precompiled packages for cpc-dev-tool-chain. This should bring the benefit of many platforms with the convenience of one download for ready-to-use integrated tools.)
I have not yet thought about the various ways RASM and other tools can be mixed for versatility and convenience. First idea is to have projects automatically call Rasm for all files named like
*.rasm.
The short-term goal motivating all this is "just" to incorporate music exported by Arkos Tracker in my existing ongoing SDCC/SDASZ80-based project JustGet9.
IssueIntegration is done by downloading source code from some "official" URL.
The current URL to source code is https://www.cpcwiki.eu/forum/programming/rasm-z80-assembler-in-beta/?action=dlattach;attach=30425 (https://www.cpcwiki.eu/forum/programming/rasm-z80-assembler-in-beta/?action=dlattach;attach=30425) which:
* does not show clearly what is downloaded
* does not make obvious how to get back to the conversation
* feels brittle (we have seen some CPC-related forum disappear)
* tends to download to files named like
index.html?action=dlattach;attach=30425 or even
?action=dlattach;attach=30425.
SolutionI wish the source code would be available from a site offering nice and stable URLs. Have you considered putting it on some code sharing platform like github?
Such solution also has convenient features like automatically building and serving binaries for various platforms whenever you push a new release.
For example you can visit https://github.com/ColinPitrat/caprice32/releases (https://github.com/ColinPitrat/caprice32/releases) and
consider the stable URLs presented there:
https://github.com/ColinPitrat/caprice32/releases/download/v4.5.0/cap32-win64.zip (https://github.com/ColinPitrat/caprice32/releases/download/v4.5.0/cap32-win64.zip)
https://github.com/ColinPitrat/caprice32/releases/download/latest/cap32-win64.zip (https://github.com/ColinPitrat/caprice32/releases/download/latest/cap32-win64.zip)
I see you put version numbers on your releases. What kind of version tracking tool do you use?
Thank you for your attention.
Quote from: cpcitor on 20:33, 28 February 20
Issue
Integration is done by downloading source code from some "official" URL.
there is an (un)official but stable URL since 0117 for dev users like you
http://www.roudoudou.com/export/cpc/rasm/rasm_v0119_src.zip
Quote from: roudoudou on 22:27, 28 February 20
there is an (un)official but stable URL since 0117 for dev users like you
http://www.roudoudou.com/export/cpc/rasm/rasm_v0119_src.zip
Thanks! This is a much better URL!
Oh. This URL works when using a known interactive browser but fails when using Wget, which is what cpc-dev-tool-chain uses. Experimenting shows that the server rejects requests which have a
User-Agent field containing the substring
Wget.
I understand that some would had such an idea but find it somehow pointless as it's beyond easy to circumvent -- bad guys would use a different user agent on first query anyway. Were I worried about leechers on my servers, I would first host a robots.txt file at the root, following https://en.wikipedia.org/wiki/Robots_exclusion_standard which is obeyed by a number of programs like wget.
Anyway, thanks a lot!
update v0.120
- BIT,RES,SET may use deferred shifting value
- BANK directive may use NEXT as parameter to switch to next BANK space
- operator assignment are now supported
- may use tags in filenames with SAVE directive
- warn for huge shifting and force result to zero (as it's an architecture independant operation)
executables later...
update v0.121
- early stages MODULE support
- \ support (experimental)
- APlib Ultra integration (load&crunch + crunched section)
- bugfix segfault when trying to assemble a file that does not exists
- bugfix segfault with opened comment '/*' until the end of the file
- bugfix DEFB calculation with $ after crunched section
- proximity label beginning with BRK will generate an exportable breakpoint
- LIMIT directive evolution (mostly for #FFFF writing case)
- crunched INCBIN may use offset/length/remap before crunch
update v0.122
- proximity label enhancement with macro inception and loops
- new directive MODULE
documentation updated (Thanks Siko!) in v122!!!
and the release note as there is some oversights:
- you may use "BANK NEXT" to open next bank (snapshot or cartridge mode), useful when you are supposed to change bank order often
- you may SAVE a file with HOBETA header => SAVE 'myfile.bin',start,size,HOBETA
update v0.124
- new directive DF/DEFF in order to output Microsoft IEEE-754 40bits real
- pasmo compatibility option for DEFB/DEFW with multiple output and reference to current adress
update v0.123
- new option to treat warnings as errors
- bugfix segfault with empty struct declaration
- bugfix v0.121 regression for INCWAV
- check labels,variables and alias when declare macro name
Those versions numbers (0.1xx) with a program that will never reach 0.2 always make me smile. ;D
https://en.wikipedia.org/wiki/Software_versioning (https://en.wikipedia.org/wiki/Software_versioning)
just fix another (important) bug...will push win executables later
- bugfix EQU with current adress reference and crunched zones integration
update v0.126
- Rasm is able to mix LZsegments and contiguous ORG sections
example:
tabeul
defw script0
defw script1
defw script2
script0
org #4000,$
lz49
start1 : jr end1 : defs 100: djnz start1
end1
lzclose
org $
script1
org #4000,$
lz49
start2 : jr end2 : defs 100 : djnz start2
end2
lzclose
org $
script2
org #4000,$
lz49
start3 : jr end3 : defs 100 : djnz start3
end3
lzclose
update v0.127
- bugfix some memory leaks
windows execs soon
update v0.128
- bugfix moar memory leaks
- label code clean-up
new execs
update v0.129
- bugfix read overrun in pre-processor
- bugfix read overrun in snapshot encoding
- bugfix AMSDOS header creation with filename that contains a path
- force memory cleanup with MorphOS
- when a variable cannot be computed, check for directive names to avoid confusion
Yay! Thanks for using GitHub.
I'm subscribed to new releases, and that would make things easier for me!
Btw, if is OK to send you pull requests... may be we could add a Makefile for example :D
Quote from: reidrac on 16:18, 11 June 20
Yay! Thanks for using GitHub.
I'm subscribed to new releases, and that would make things easier for me!
Btw, if is OK to send you pull requests... may be we could add a Makefile for example :D
Yeah, all new releases will be posted to github. I will come back here to mention stable releases or huge updates :)
Rasm does not need makefile and compilation command line are in the header of rasm.c but i may add some compilation .bat .sh or mention this in the readme :)
Quote from: roudoudou on 16:47, 11 June 20
Yeah, all new releases will be posted to github. I will come back here to mention stable releases or huge updates :)
Rasm does not need makefile and compilation command line are in the header of rasm.c but i may add some compilation .bat .sh or mention this in the readme :)
Thanks for opening a github repo! https://github.com/EdouardBERGE/rasm
cpc-dev-tool-chain (https://github.com/cpcitor/cpc-dev-tool-chain/tree/master/tool/rasm) started incorporating rasm recently, though I have not adjusted makefile rules for user projects.
The issue is: by default rasm likes
.asm suffix, while in SDCC, assembly source is
.s (probably consistent with embedded systems traditions).
SDCC
generates .asm files containing assembly
generated by the C compiler (very handy to check for efficiency).
Thus,
make clean deletes
.asm files and they are excluded from source code history.
Currently I use .rasm for assembly source to be compiled by RASM, vs .s for assembly source to be compiled by sdasz80.
Quote from: cpcitor on 08:38, 12 June 20
Thanks for opening a github repo! https://github.com/EdouardBERGE/rasm (https://github.com/EdouardBERGE/rasm)
cpc-dev-tool-chain (https://github.com/cpcitor/cpc-dev-tool-chain/tree/master/tool/rasm) started incorporating rasm recently, though I have not adjusted makefile rules for user projects.
The issue is: by default rasm likes .asm suffix, while in SDCC, assembly source is .s (probably consistent with embedded systems traditions).
SDCC generates .asm files containing assembly generated by the C compiler (very handy to check for efficiency).
Thus, make clean deletes .asm files and they are excluded from source code history.
Currently I use .rasm for assembly source to be compiled by RASM, vs .s for assembly source to be compiled by sdasz80.
When there is no extension i try
char *LTryExtension[]={".asm",".z80",".o",".dam",".mxm",".txt"
But if you give the fullname rasm will load it whatever the extension is, so i do not understand where is the issue?
Quote from: roudoudou on 16:47, 11 June 20
Rasm does not need makefile and compilation command line are in the header of rasm.c but i may add some compilation .bat .sh or mention this in the readme :)
Please don't reinvent the wheel. Makefiles are useful even for single-file builds because they remove the need for "some compilation .bat .sh or mention this in the readme". The simplest makefile has one more line than a shell script, and then it builds with "make" just like every other project that uses it.
Quote from: pelrun on 10:32, 12 June 20
Please don't reinvent the wheel. Makefiles are useful even for single-file builds because they remove the need for "some compilation .bat .sh or mention this in the readme". The simplest makefile has one more line than a shell script, and then it builds with "make" just like every other project that uses it.
Well, in perfect world maybe. But in real life Makefiles never work out of the box and you always have to dig inside, and to moan because it is over-complicated for nothing. :P
Quote from: OffseT on 17:47, 12 June 20
Well, in perfect world maybe. But in real life Makefiles never work out of the box and you always have to dig inside, and to moan because it is over-complicated for nothing. :P
it's obviously one makefile per OS so... why not a script? => because there is only one command line to compile rasm ;D
Read the funny manual!
Quote from: cpcitor on 08:38, 12 June 20
Thus, make clean deletes .asm files and they are excluded from source code history.
Currently I use .rasm for assembly source to be compiled by RASM, vs .s for assembly source to be compiled by sdasz80.
Use .z80 for example (I prefer it because I can set specific syntax highlighting for Z80).
Quote from: OffseT on 17:47, 12 June 20
Well, in perfect world maybe. But in real life Makefiles never work out of the box and you always have to dig inside, and to moan because it is over-complicated for nothing. :P
Don't blame friends that help youYou're conflating. Variety of build environments is not
Make's fault.
Complaining like this is like blaming a friend that helps you because they don't have a solution for every problem of your life.
Different build systems for different kind of programs.Programs with tons of dependencies on modern features often use different, higher level tools, because in those cases, pure makefile-based workflow cannot simply express the needs. Perhaps you have suffered some program where author wrote a big makefile in a situation where it was not the simplest solution.
Simple program, simple makefile.rasm is simple to build, it uses basic file APIs along with standard input and output. It's typically a program perfectly suited for a simple makefile.
A simple makefile is where people are looking first.When getting source code, people look at file names for hints.
Makefile is a traditional entry point.
A simple makefile is machine-executable documentation.Programs need it too. IDE, packaging infrastructures, automated quality assurance tools like travis need machine-readable instructions. A two-line
Makefile eases integration and avoids bugs due to different contexts using different build options.
No makefile feels like the author is too lazy, doesn't know how to write a two-line makefile.
Simple and convenient solution that always worksFor the user, typing
make is shorter than other options.
Even
make -f Makefile.other is only a few more keystrokes using
Tab key.
Such directory layout is very clear, shows that author is seasoned about portability, with default
Makefile for gcc-compatible build environment and took care of making things easy for users of a number of platforms:
Makefile
Makefile.win-msvs
Makefile.dos-watcom
Makefile.morphos-gcc
Makefile.macos
source.c
In the case of RASM it *will* work out-of-the-box.
I wasn't going to push the point quite that hard. In fact I forked RASM so I could write the Makefile myself but I was beaten to the punch. Cheers!
Is not the end of the world, really.
I also write my own Makefile for rasm, for example for the rasm version I used in Kitsune's Curse:
all: rasm
rasm: rasm_v0119.c
gcc -s -O2 $< -o $@ -lm -lrt -march=native
clean:
rm -f rasm
.PHONY: all clean
I use GNU Make, but you can make it generic enough.
Quote from: reidrac on 08:17, 13 June 20
Is not the end of the world, really.
I also write my own Makefile for rasm, for example for the rasm version I used in Kitsune's Curse:
You makefile is nice and complete with usual patterns.
I went straight to the point when integrating RASM in cpc-dev-tool-chain (https://github.com/cpcitor/cpc-dev-tool-chain): after automatically fetching and unpacking rasm source, cpc-dev-tool-chain build system copies a strictly two lines makefile (https://github.com/cpcitor/cpc-dev-tool-chain/blob/master/tool/rasm/Makefile.rasm) into the source directory and calls it.
release v1.1 ;)
https://github.com/EdouardBERGE/rasm/releases/tag/v1.1
https://github.com/EdouardBERGE/rasm/releases/tag/v1.2
release v1.2
- nightly bugfix
- bugfix memory leaks and error management with includes in embedded rasm
- bugfix INCLZ4 directive
- many new autotests for include and crunch
- RUN directive do not force PPI configuration to #C0 if there is no second argument
- produce zero size file when there is no breakpoint
- new command line option -amper in order to use ampersand for hex values
- new directive BREAKPOINT_Z80 to produce #ED,#FF opcode
- new directives beginings GETTICK, DURATION (only a few instructions supported)
- new ROM mode to automatically save multiple numbered ROM files
- ability to split 16 bits registers in macro declaration (example: hl.low or {register}.high )
documentation will be updated later
new release v1.3
https://github.com/EdouardBERGE/rasm/releases/tag/v1.3
- extended cartridge support
- new directive LZSA1, LZSA2 for crunched code sections
- new directives INCLZSA1 and INCLZSA2 for binary import and LZSA crunching
- new directives XORMEM and SUMMEM to generate checksum of a memory area
- new directive TIMESTAMP to output date/time
- new TAPE option for SAVE directive
- new DMA import options with INCBIN directive (new checks & warnings)
- new enhanced instructions LD IX/IY,BC/DE & LD BC/DE,IX/IY
- new tag {SLOT} for extended cartridge management
- new suffix .HIGH and .LOW to split 16bits register in macro definition
- new option -msep to specify separator for labels inside modules
- new option -amper to use ampersand for hex values
- directive BRK now generates #ED,#FF opcode
- bugfix byte order for Microsoft real format
- bugfix DSK header with nightly build
- bugfix 16bits PCM wav import
- do not warn for missing file with INCLUDE in disabled condition
- do not export struct definition with symbols
- many warnings removed, cleanup, some draft for future functionalities
Great job done!
Hint to new users: You find the documentation inside the source code.
Quote from: GUNHED on 15:40, 24 November 20
Hint to new users: You find the documentation inside the source code.
always get the latest PDF on master branch because documentation is never up to date when i'm doing a release !
Writing documentation suxx. (I know that from own projects). But nevertheless we all need it. Thanks for this, it's made in an "easy to be understood" way. :) :)
Quote from: GUNHED on 15:50, 24 November 20
Writing documentation suxx. (I know that from own projects). But nevertheless we all need it. Thanks for this, it's made in an "easy to be understood" way. :) :)
anyway i'm always ok to answer any question by mail ;D
FR/EN documentation updated - thanks Siko!
download on github
https://github.com/EdouardBERGE/rasm/blob/master/documentation_EN.pdf
https://github.com/EdouardBERGE/rasm/blob/master/documentation_FR.pdf
Ouf ^^
https://github.com/EdouardBERGE/rasm/releases/tag/v1.4
new release v1.4
new TAPE output code from CNG in GPL2
new directive BUILDTAPE
new directives GETNOP to count Amstrad nops
new directives GETTICK to count Z80 ticks
new DMA options for Amstrad Plus WAV import
new LZSA directives for LZSA1 and LZSA2 compression
new ZX0 directives for ZX0 compression and backward compression
new CONFINE directive
new command line option for amper hex values usage
new command line option for quick ZX0 compression
new postfix .low and .high to split registers in macro definition
BANK tag may process proximity label
bugfix some warnings
bugfix IN A,(C) timing in rasm
bugfix moar timings in documentation
bugfix SRL reg16 alias
bugfix segfault when LZ section was not closed
bugfix compilation without third parties
latest directives will be documented soon (i hope :P )
Quote from: roudoudou on 08:58, 22 February 17
Official repository is now on github
https://github.com/EdouardBERGE/rasm (https://github.com/EdouardBERGE/rasm)
Github is a pain, anything else I would appreciate.
Took one click to get here - https://github.com/EdouardBERGE/rasm/releases
Quote from: GUNHED on 21:51, 03 February 21
Super chaotic, can't find it. Github SUXX!! (And I tell the other members of the group I'm a member all the time).
Can you please put something somewhere just to click at. I'm not willing to waste (now more) than 30 minutes to search a download for something I just can't find.
i put the release link each time i talk about a release :)
see immediate upper post
Quote from: GUNHED on 21:51, 03 February 21Super chaotic, can't find it. Github SUXX!!
:picard:
git clone ...
and compile for your platform.
What's wrong with a download link (working!) of a ZIP or whatever?
Quote from: GUNHED on 23:42, 03 February 21
What's wrong with a download link (working!) of a ZIP or whatever?
There is a direct link and it's working :-X
Then there is many binaries, just get the one you need, no useless ZIP or whatever because binaries are auto-crunched
(https://i.postimg.cc/CKtNQLD4/lapincompris.png)
Can we move on another subject please?
Maybe it's my Windows 7 or my browser, it's a pain in the back for me. 'Just klick and download' doesn't work for me. But nice if it works for everybody else.
Hi There ....
I am in the process of porting som old code to RASM, so far going pretty well
But I get a strange error when trying to assemble using directives defb, defm...
this eg.
; test.asm
org #4000
defm 'Banks: Name: SP AF',39
or when using defs...
I get this error:
Pre-processing [test.asm]
[test.asm:7] quote opened was not closed
Assembling
1 error
I am really lost... What am I doing wrong... Tried with defb directive as well!
Hope someone can help
Regards,Ygdrazil
PS. The code I am porting is from Maxam...
[/code]
change single quote with double quote for strings and DEFB
but i agree this is a bug i will fix ;D
Thanks :D !
Quote from: roudoudou on 21:24, 27 February 21
change single quote with double quote for strings and DEFB
but i agree this is a bug i will fix ;D
just tried to compile this on my Pi400 (Raspbian 64Bit) but I get an error :
rasm.c: In function 'Assemble':
rasm.c:17771:10: error: '*debug' is a pointer; did you mean to use '->'?
debug -> run=run;
^~
->
rasm.c:17771:17: error: 'run' undeclared (first use in this function)
debug -> run=run;
^~~
rasm.c:17771:17: note: each undeclared identifier is reported only once for each function it appears in
rasm.c:17772:10: error: '*debug' is a pointer; did you mean to use '->'?
debug -> start=minmem;
^~
->
make: *** [makefile:102: prod] Fehler 1
Hints ???
how do you compile it ?
Since it has a makefile I'll do a MAKE in console :laugh:
Its my fault
Will fix it
https://github.com/EdouardBERGE/rasm/releases/tag/v1.5
Release v1.5
new directive DELAYED_PRINT
new directive STARTINGINDEX + REPEAT options
new directives PROCEDURE, EXTERNAL, BUILDOBJ for kind of objects export
new shortcut ENDMODULE
new autotests + debug struct info RUN+START
new external function for emulators and assembling into RAM
ROM flat output for BUILDROM directive
use _setmode only with Visual Studio 14.0 and below
use custom strnlen with BorlandC
use only declarations from rasm.h
bugfix IX/IY invalid syntaxes
bugfix INCBIN wav preamp with DMA options
bugfix ZX snapshot output + RUN bugfix
bugfix TIMESTAMP and custom charset
bugfix Borland compatibility
bugfix segfault with wrong char in DEFB/DEFM string
bugfix segfault with quote not closed in the very last directive
bugfix INTn prefix behaviour
bugfix LD reg16,(IX/IY) alias
warn about ORG inside crunched section
compute alias values before crunching sections, this fix some side effects of EQU inside crunched sections
ZX0 firmware compatible decrunch routine
Linux version compiled with GCC v9.3.0
MS-DOS version compiled with Open-Watcom 1.9
Windows version compiled with Microsoft Compiler v19
Documentation is almost up to date (except release version number ^_^ )
new release :)
https://github.com/EdouardBERGE/rasm/releases/tag/v1.6
- ZX0 cruncher upgraded to v2 + new Z80 decrunchers
- do not export command line define(s)
- bugfix ZX0 backward compression
- bugfix automatic filetype search for main source
- bugfix autotests with 3rd parties disabled
- bugfix include paths search
- bugfix IFUSED, IFDEF, IFNDEF when used with MODULE directive
- bugfix file output with HOBETA header
- new option to export ROM description
- new option to export label with original case
for people following latest commit, i rewrote the floating point conversion to be more accurate (directives DEFR or DEFF)
still not enough evolutions/bugfix to make a release
new release 1.7
https://github.com/EdouardBERGE/rasm/releases/tag/v1.7
- bugfix snapshot v3 first chunks when memory cannot be crunched in RLE
- bugfix negative rounding for REAL conversion
- bugfix segfault with UTF8 char usage in strings
- bugfix quote starting with escaped char
- bugfix macOS support, new target install
- bugfix label import
- bugfix GETNOP/GETTICK LD (HL),im8 + some missing instructions added
- bugfix breakpoints missing when exporting for snap and breakpoint file
- bugfix undefined behaviour with EQU usage before declaration
- new Amstrad/Microsoft conversion to 5-bytes REAL with full precision
- new math function FILESIZE to get file size on disk
- new math function GETSIZE to get opcode size
- new poker option with a few cipher methods
- new directive CIPHERMEM to cipher memory
- new directive SNAPINIT to initialize memory with a snapshot
- new CONFINE option in order to enforce location
- new UTF8 support to convert legacy french or spanish char to proper Locomotive Basic values + new command line option
- more symbol exports with "ignore case" (and faster)
- GTILES option for INCBIN to import tiles with gray encoding
documentation NOT updated since 1.6
:D :D :D
Thank you.
Quote from: roudoudou on 22:14, 11 April 22new release 1.7
I tried to compile my pasmo program and I failed. I used
rasm -pasmo pi-cpc-cpm3.asm
and got a lot of error messages. The original pasmo works flawlessly. I have attached files of my old pasmo project.
Quote from: litwr on 07:00, 06 September 22Quote from: roudoudou on 22:14, 11 April 22new release 1.7
I tried to compile my pasmo program and I failed. I used
rasm -pasmo pi-cpc-cpm3.asm
and got a lot of error messages. The original pasmo works flawlessly. I have attached files of my old pasmo project.
yeah, Pasmo compatibility is to compile old Pasmo projects
i wrote the compatibility long time ago when Pasmo seemed abandonned
as Pasmo is back with active developpements, just use Pasmo if you like Pasmo syntax
8 months since the 1.7 release, here is an updated documentation (with almost all last Rasm improvements)
French documentation is now on http://rasm.wikidot.com/
English documentation is now on http://rasm.wikidot.com/english-index:home
Fantastic!
Thank you so much!
new release :)
https://github.com/EdouardBERGE/rasm/releases/tag/v1.8
- new up to date documentation on wikidot => http://rasm.wikidot.com/home:home
- new conditional directive ELSEIFNOT
- new math function IS_REGISTER
- new directives CPRINIT and SNAPINIT in order to initialise RASM memory with a cartridge or a snapshot
- new command line option to handler macro calls on multiple lines
- MAP output improvements
- MODULE support for EQU => Alias are now inside modules, like labels
- CHARSET can be used with string to string conversion
- removed ENDREPEAT and ENDREP literaly unused directives
- bugfix WATCOM compatibility issue
- bugfix STR endmark with CHARSET conversion
- bugfix CONFINE directive with ENFORCE parameter usage
- bugfix backslash usage with CHARSET defined for it
- bugfix memory leak with map output and alias usage
- bugfix memory overrun at memory cleanup
- bugfix preprocessor with include filename strictly ending the line
with RASM, is there a way to generate the relocation file so that I can make a relocator? or do i need to assemble it twice at different locations then create the file from that? - just a file with series of addresses for which to add a 16bit offset would be more ideal - in binary format.
Interesting someone else asked for a similar thing in a different forum: https://www.z88dk.org/forum/viewtopic.php?t=9116
I am guessing my approach would be to assemble the code at 0000 and then again at 1111 and compare the differences and make an address list.
Quote from: zhulien on 02:41, 02 May 23with RASM, is there a way to generate the relocation file so that I can make a relocator? or do i need to assemble it twice at different locations then create the file from that? - just a file with series of addresses for which to add a 16bit offset would be more ideal - in binary format.
Interesting someone else asked for a similar thing in a different forum: https://www.z88dk.org/forum/viewtopic.php?t=9116
I am guessing my approach would be to assemble the code at 0000 and then again at 1111 and compare the differences and make an address list.
an external relocator is possible, i made a prototype years ago where you can declare procedure etc. https://github.com/EdouardBERGE/rasm/issues/8
but as .REL files are not really documented...
it may be possible to make an relocation table inside the binary (at the beggining?) or another file but i guess you need to be more specific (contact me via email)
Quote from: roudoudou on 06:56, 02 May 23Quote from: zhulien on 02:41, 02 May 23with RASM, is there a way to generate the relocation file so that I can make a relocator? or do i need to assemble it twice at different locations then create the file from that? - just a file with series of addresses for which to add a 16bit offset would be more ideal - in binary format.
Interesting someone else asked for a similar thing in a different forum: https://www.z88dk.org/forum/viewtopic.php?t=9116
I am guessing my approach would be to assemble the code at 0000 and then again at 1111 and compare the differences and make an address list.
an external relocator is possible, i made a prototype years ago where you can declare procedure etc. https://github.com/EdouardBERGE/rasm/issues/8
but as .REL files are not really documented...
it may be possible to make an relocation table inside the binary (at the beggining?) or another file but i guess you need to be more specific (contact me via email)
It would be great if there was an option to have a table of addresses at the start or end (optional). For me the end is best, because I can load an application, relocate and write over the relocation table, I guess someone could do that at the start if they prefer that, but... the start is more often a header or where program execution starts - so it would be less common. If at the end, a simple table of 16-bit values, the first being a count of how many 16-bit values follow. Those values would all be addresses (assuming 0000 is the start address) for which a 16-bit offset would be added. The 16-bit offsets of course up to the developer, but it makes their (and mine) life easier if we assemble the code at 0000 also so it is just a simple addition of the load address to each of those addresses in the table.
It's a fantastic assembler and now use it for my Z80 dev when cross assembling.
I found sjasmplus has pretty much that exact feature (it seems). it works by having 2 assembler directives.
relocate_start and relocate_end which you wrap around the entire code you want to relocate, oddly the examples also put the following assembler variables within those.
relocate_table and relocate_count. This means the count can be anywhere assigned to a dw for example. and the table put anywhere also. I'd rather use rasm if i have a choice.
Quote from: zhulien on 23:24, 02 May 23I found sjasmplus has pretty much that exact feature (it seems). it works by having 2 assembler directives.
relocate_start and relocate_end which you wrap around the entire code you want to relocate, oddly the examples also put the following assembler variables within those.
relocate_table and relocate_count. This means the count can be anywhere assigned to a dw for example. and the table put anywhere also. I'd rather use rasm if i have a choice.
Yep, there is something similar with winape assembler, will dig into it
i made a prototype version of relocation section, the directives names are different from winape/sjasm because the behaviour is not the same
what i understand from winape is that you can only relocate 16 bits pointers which is a very simplified version of relocation
my version can handle 16bits as 8bits pointer usage, distinguishing low weight and high weight usage cases
short doc for the prototype => http://rasm.wikidot.com/directives:relocate
Quote from: roudoudou on 11:32, 21 May 23i made a prototype version of relocation section, the directives names are different from winape/sjasm because the behaviour is not the same
what i understand from winape is that you can only relocate 16 bits pointers which is a very simplified version of relocation
my version can handle 16bits as 8bits pointer usage, distinguishing low weight and high weight usage cases
short doc for the prototype => http://rasm.wikidot.com/directives:relocate
Can you elaborate on what the 8bit pointers are? I did read your PMs about lo and hi, are they assembler directives or macros? or unofficial Z80 instructions?
Quote from: zhulien on 12:48, 22 May 23Quote from: roudoudou on 11:32, 21 May 23i made a prototype version of relocation section, the directives names are different from winape/sjasm because the behaviour is not the same
what i understand from winape is that you can only relocate 16 bits pointers which is a very simplified version of relocation
my version can handle 16bits as 8bits pointer usage, distinguishing low weight and high weight usage cases
short doc for the prototype => http://rasm.wikidot.com/directives:relocate
Can you elaborate on what the 8bit pointers are? I did read your PMs about lo and hi, are they assembler directives or macros? or unofficial Z80 instructions?
it's high weight or low weight, it's useful to compute addresses by spliting weight sometimes
hi and lo are math functions (common with other assemblers) to get lo w or high w of a 16 value
forget about it, it's barely like using ptr>>8 or ptr&0xFF as immediate value
Is low weight and high weight a specific RASM feature? I've never heard of such before.
Quote from: zhulien on 12:55, 22 May 23Is low weight and high weight a specific RASM feature? I've never heard of such before.
it's a very common feature of many assemblers ;D sometimes with high/low keyword
SJASM for some things which breaks the relocation throws up a warning, perhaps hi and lo could do that - and people who need relocation wouldn't use those - it is 'sort of' a copout, but it is a reasonable one until a way to resolve that could be found.
Quote from: zhulien on 13:11, 22 May 23SJASM for some things which breaks the relocation throws up a warning, perhaps hi and lo could do that - and people who need relocation wouldn't use those - it is 'sort of' a copout, but it is a reasonable one until a way to resolve that could be found.
if there is no 8bits usage, there wont be 8bits output
(https://i.ibb.co/7tZ8SHm/cpc1.png) (https://ibb.co/v4Tgcbn)
Might not be much in the grand scheme of things, but rasm helped me do my first assembly language program for the CPC ever. Z80 assembler defeated me when I was a kid, but 30 years later, mwahahahaha! So thank you Eduoard! (I'm using VSCode/Rasm/Caprice32 on Ubuntu 22.04 LTS)
new release out! https://github.com/EdouardBERGE/rasm/releases/tag/v1.9
Rasm v1.9 - 2023 Guilty Pleasure
- ludicrous speed enhancement
- new struct export for rasm embeded
- enforce LD r8,im8 usage (to avoid confusion when it's possible between memory reference and calculation using parenthesis)
- enforce AMSDOS name proper format
- may export files on DSK with another user
- new REMU chunk in snapshots for debug usage and precise breakpoints
- new RMxx chunks in snapshots for ROM usage
- new directives ROMBANK to manage ROM in snapshot output
- new directives SRL8 and shift aliases RLC/RRC for 16 bits registers
- new conditionnals RST #38
- audio filtering for DMA conversion
- various prototypes in order to design relocatable code (still in progress but documented)
- changed DJNZ timing to "loop"
- bugfix some autotests and leaks with embeded Rasm
- up to date documentation
- each OS build of rasm is still tested with more than 1100 automatic tests
builds for windows XP, windows x64
builds for MacOS ARM and MacOS Intel
I have a suggested feature I haven't seen a z80 assembler support, what are your thoughts.
Normally people code their assembly language program with a 64k memory map and they need to deal with complex memory banking if they want large programs and/or other overlay methods.
My suggestion is this. I can elaborate if you need, but it is it introduce a couple of memory models with supporting directives.
Model directive:
Model small ; default behaviour no different to now
Model large ; 4mb memory model
Model gigantic; 16mb memory model
Instead of programs being assembly purely from org to himem as in small... large and gigantic assemble the code unto the banks instead as follows.
Bank directives:
Set Global 0040, 3fff, 8000, a410
Set Banked 4000, 7fff ;can be hardcoded but if flexible can work on other platforms
Global ; code after this is assembled in the global areas
Banked ; code here is assembled only inside the banks
Set farcall blah ; blah is the farcall function in global ram
Align keyword in front of labels that need alignment.
Banked code is byte aligned to either 64bits for large memory model, or 256 bytes for gigantic model whenever a call or jump or label is referenced that is defined within the banked ram and aligned. This allows a small global farcall subroutine to make fast 16bit far calls.
Large memory model suits very nicely large ram or rom assemblies up to a 4mb plus binary without much thought. And gigantic also but with virtual memory support in the farcall function or a future 16mb ram expansion.
It means I can make a high level language generate rasm source and not be constrained by memory and memory now is cheap.
CPC users have no excuse to not buy a 2mb or 1mb Gemini card.
Correction:
Banked code is byte aligned to either 64 bytes for large memory model, or 256 bytes for gigantic model
You should read the documentation, there is already a complete banking system
For example it's possible to assemble in RAM and ROM (lower and upper) when building snapshots, you may use BANK gathered by 64K or use a 64K space for a single 16K bank
Alignment is already possible with ALIGN directive and also CONFINE for small arrays
And if you need moar than what is already existing, you can simply BANK as many as you want, temporary 64K space (and use SAVE)
Oops
I have now read the memory management and alignment documentation. Great to see it there. I was hoping a single assembly could handle all the addressing and substitute necessary far calls instead of the programmer. Rasm is open source right? Maybe I can try figure out how to add the large and gigantic schemes. They are sort of like the ROM schemes but not totally. As mentioned a single 16bit byte aligned address can address either 4mb or 16mb. The reason we don't align ever address is... neighboring functions in a same bank don't need to do far calls and can freely call eachother normally.
Quote from: zhulien on 07:53, 21 June 23I have now read the memory management and alignment documentation. Great to see it there. I was hoping a single assembly could handle all the addressing and substitute necessary far calls instead of the programmer. Rasm is open source right? Maybe I can try figure out how to add the large and gigantic schemes. They are sort of like the ROM schemes but not totally. As mentioned a single 16bit byte aligned address can address either 4mb or 16mb. The reason we don't align ever address is... neighboring functions in a same bank don't need to do far calls and can freely call eachother normally.
You said you "can make a high level language generate rasm source and not be constrained by memory and memory now is cheap." so it wont be to the programmer charge :D (only your generator)
From my point of view you may already use rasm to use 16M of BANK if you want, charge to your programm to track what you do (i'v done myself an 8M ROM proof of concept (working!) years ago)
So, go for it!
There is a difference in me working out the memory usage and deciding what goes into a bank and actually generating code than me generating assembler for rasm. The latter is easier at my end. If I generate code then it becomes a full compiler.
To use the 16kb blocks, rasm currently won't track what is a local or far call will it?
you can organize yourself the way you want with many kinds of labels => http://rasm.wikidot.com/label:labels
As the coder, how will I know before assembly what is going to fit in a bank before overflowing to the next bank, and moving a whole function to the next bank and then changing any labels that were local into far calls? Only the assembler know that unless I want things to be in specific banks.
Quote from: zhulien on 09:50, 21 June 23As the coder, how will I know before assembly what is going to fit in a bank before overflowing to the next bank, and moving a whole function to the next bank and then changing any labels that were local into far calls? Only the assembler know that unless I want things to be in specific banks.
You generator will have to count what he's doing: basics!
It output any instruction, he already know where he is, you can also buffered any of your fonction to defer output, it's a generator problem, not an assembler problem (all of my generators do that)
The problem with trying to hide how banking work is that banking takes instructions and thus affects state of the processor. So silently replacing a CALL with a bunch of instructions to manipulate memory, then do a CALL, then revert memory might subtly introduce bugs. If, for example, the called function relied on the state of the carry flag etc. So then you have to start making the assembler defend against this by PUSHing all the registers etc, impacting performance unnecessarily and possibly causing other issues with stack usage.
At some point you're either writing assembler, with all the low level management requirements it brings, or you want a higher level language like C, which can abstract away some of the complexity for you.
I would do it this way, pass 1 almost as usual, but instead of counting 1 set of label addresses etc. If it is identified that anything is within the banking RAM, then we introduce a pass 1b which is almost the same as pass 1, but now works out of those labels, which would be far addresses and which calls would now be changed to far calls. Pass 2 as per normal but honor what was identified as far calls.
Far calls I would substitute as either... a defined block of code like a macro, or hardcoded: push hl; ld hl, nnnn; push hl; ret; yes, it is more than 3 bytes hense why we had a pass 1b.
But, nnnn is the address of the bank routine that would itself rotate the stack then push current bank, push current return address, set new bank and return to the call address - of course it returns to the proper location upon the far call returning.
Why do this? because it is still low level, but... gives an "almost" flat 4mb or 16mb memory model for programmers so they can just code their software and load assets without too much banking headaches. If you think a farcall is expensive, then put functions that are often called in loops neighbouring eachother so that farcalls are not often as much called in loops.
Anyway, to me it is a good novel idea :D
Problems I can see:
- You increase code size in Pass 1B, so all the addresses you calculate (including what is in banked addresses) are wrong. Really you need a linker to handle this better.
- It's not sufficient to only manipulate CALLs like this, since a banked routine may no longer be in the same address space as the data it needs to access, so you have to come up with convoluted modifications for absolutely everything: for example an LDIR might cross multiple banks because you've hidden the details of it, so you have to replace it with code that can detect it needs to bank switch. And pretty soon almost every assembly instruction has to get swapped out with a CALL to a routine that does that instruction but for a flat memory model.
It would be much, much easier to manage this in a higher level language, which can more easily abstract away the intent of code and generate more optimal assembly for it.
or your generator makes code of all your functions, he already knows the boundaries of all functions, can sort them by hierarchy calls and optimise the very last calls by placing them in the same bank (he already knows also the function minimum size and maximum size)
once the first optimisation step is done, he can also gather functions in less bank using a simple cargo loading algorithme
finally any assembler will assemble the source
done ;D
have you never wanted to assemble something larger than 40K without mucking around with banking?
I have looked at the supersnapshot functionality and the C code already knows what bank the labels are in as well as the orgzones, so *there is 'almost' logic in place to allow for programs in RAM that can be up to 4mb or 16mb*. To me that is a good step towards allowing better software to be more easily coded on CPC.
I do understand that a full high level language can do all that, if it compiles to native code. But besides macros and a LOT of planning about memory locations, having the assembler do that allows someone to code low level with little mucking around.
A supposed memory map would be such as:
(global variables and buffers)
0040 - 3fff
8000 - a410 (perhap slightly lower) and also contains stack and a few banking service routines configured by assembler macros/directives
(medium, large and gigantic almost-automatic banked memory)
4000 - 7fff from bank 0 to bank 256 (in medium 512KB mode) - far address support with byte alignment at 4 for FAR REFERENCED or ALIGNED labels only
4000 - 7fff from bank 0 to bank 256 (in large 4MB mode) - far address support with byte alignment at 64 for FAR REFERENCED or ALIGNED labels only
4000 - 7fff from bank 0 to bank 256 (in gigantic 16M mode) - far address support with byte alignment at 256 for FAR REFERENCED or ALIGNED labels only
The whole point is that a user doesn't need to work out which labels are far and deal with the far addresses as 16 bits instead of e.g. 24 or 32 bits. And we would have 'almost' a flat 4mb or 16mb memory model for most part. Data and such of course, you can code your blit routines to be in global RAM and use 16bit far addresses since they would be labels that are far or aligned.
Having only 16K of usable data would make having 16MB of RAM pretty pointless though. And the minute you need your data to be pagable the whole scheme falls down - something that just doesn't need to happen with a high level language doing this for you.
it's not 16k of usable data, it's 16k of "global" usable data / buffer space. Anyway, it was a thought because RASM already supports quite a lot of what would have needed to be done anyway out of the box, just not all the way there.
I modified a small c compiler so that the following memory layout occurs and i am assembling with rasm.
0040 to 3fff for heap
4000 and up for logic followed by literals and workspace
The literals and workspace I could fit at 8000 and below himem if the logic wasn't so big.
So... I will try make it a rom to see what happens. But if the banking as mentioned was already in place then it would just work...
The c compiler can compile itself which is why I chose this one.
If I choose the cpr models how do the calls between 16k roms work?
Quote from: zhulien on 21:57, 21 June 23it's not 16k of usable data, it's 16k of "global" usable data / buffer space. Anyway, it was a thought because RASM already supports quite a lot of what would have needed to be done anyway out of the box, just not all the way there.
Yes, but that's effectively got to be your entire "heap". Any data that any routine accesses has got to be accessible by a 16-bit pointer, because the Z80 doesn't really have the flat memory model your code wants to pretend it does so anything you want to pass between functions either needs to live in a register or somewhere in the main 64K of address space.
I think it's going to be a very weird program that needs nearly 16MB of code and just 16K of heap space. Most 128K games, for example, use the extra memory almost exclusively for data and not code.
Quote from: zhulien on 07:16, 22 June 23If I choose the cpr models how do the calls between 16k roms work?
There is no such thing as a call between ROMs. The code has to arrange the memory map into a suitable fashion and then do an ordinary CALL and then arrange it back again afterwards as required.
Actually I have a heap across banks too, but it is not yet used by the c compiler, only used by assembler code. I plan to make it accessible to the c compiler though. Also virtual memory so that 128k users can have 4mb of vm.
There are multiple ways to go from one rom to another as is the same with ram. You can in fact just flow from one to another instantly making a call a moot point. This method is useful for iterating through multi bank lists or if a function is split between 2 banks instead of wasting the space at the end of a bank. As pc always increments not decrement when executing it only us useful with forward iterating - can be heap or context switches...
With selectively aligned assets as well as functions you can then perform a far call via ram which translates the packed 16bit far address into the correct bank and aligned offset. This makes programming with far calls easier than having to deal with 24bit addresses.
Quote from: zhulien on 07:16, 22 June 23If I choose the cpr models how do the calls between 16k roms work?
Each Z80 program manages banking at his convenience...
The banking system in Rasm let the assembly knows which bank a label is located (using prefix {bank} before a label)
It's up to the programm (your generator) to take care of banking (bis repetita)
Quote from: roudoudou on 10:36, 22 June 23Quote from: zhulien on 07:16, 22 June 23If I choose the cpr models how do the calls between 16k roms work?
Each Z80 program manages banking at his convenience...
The banking system in Rasm let the assembly knows which bank a label is located (using prefix {bank} before a label)
It's up to the programm (your generator) to take care of banking (bis repetita)
Do you have an example? I did read the rasm documentation but its a bit vague to me.
Quote from: zhulien on 10:30, 22 June 23Actually I have a heap across banks too, but it is not yet used by the c compiler, only used by assembler code. I plan to make it accessible to the c compiler though. Also virtual memory so that 128k users can have 4mb of vm.
I clearly must be missing something.
Let's say I have some data stored in a heap in some arbitrary bank of RAM, let's call it A. I want to pass a pointer to it to a function that ends up in bank B, this will manipulate the data and store a pointer to it in a linked list that is in bank C.
How can I possibly do that in assembly, without using 24-bit pointers and without some advance knowledge of where that bank is and without helper methods elsewhere in RAM to read from it?
Quote from: zhulien on 11:04, 22 June 23Do you have an example? I did read the rasm documentation but its a bit vague to me.
I repeat myself but...
...it's not to the assembler to bother with that, so you have to read your machine/OS specifications
For the Amstrad CPC you can see something here https://www.cpcwiki.eu/index.php/Gate_Array#Register_3_-_RAM_Banking
Rasm offers some GA informations (prefix {page} or {pageset}) in snapshot usage but it's simplistic and designed for data, not code
So it's up to YOU to bank in #4000 or in #C000 or with 64K sets
I know how ram banking works on cpc. I don't know how to use the cpr directive of rasm.
Let's say th le code being assembled is 32kb and to be a pair of roms. Does the address go from c000 to ffff twice? These are assembly directives right? Not runtime banking commands.
http://rasm.wikidot.com/keywords:memory
Quote from: andycadley on 11:06, 22 June 23Quote from: zhulien on 10:30, 22 June 23Actually I have a heap across banks too, but it is not yet used by the c compiler, only used by assembler code. I plan to make it accessible to the c compiler though. Also virtual memory so that 128k users can have 4mb of vm.
I clearly must be missing something.
Let's say I have some data stored in a heap in some arbitrary bank of RAM, let's call it A. I want to pass a pointer to it to a function that ends up in bank B, this will manipulate the data and store a pointer to it in a linked list that is in bank C.
How can I possibly do that in assembly, without using 24-bit pointers and without some advance knowledge of where that bank is and without helper methods elsewhere in RAM to read from it?
You can do it with 16bit packed far addresses. The reason the data for a packed address needs to be aligned is because... they are packed. 4mb ram on a z80 is a lot and the packing of addresses makes programming easier with very little loss in the overall scheme.
Cartridge bank are 16K, it's up to you to split your code
QuoteBANK number
Selecting a bank number will set RASM to cartridge mode by default. If you want to access the banks of a snapshot or the ROMs, you must first declare your intention with the BUILDSNA or BUILDROM commands. The cartridge mode is basically limited to 32 ROMs. If you exceed ROM 31, RASM will automatically switch to extended cartridge mode like XPR (experimental and only supported under the hood ;)
Using BANK without parameter will open a new temporary space of 64K which will be "lost" except if you use SAVE directive obviously
WARNING: Select a BANK always open a 64K memory space whereas only 16K will be written in ROM/cartridge/snapshot mode. To let you compile at any address, the beginning of this 16K space will be the first written byte. I recommend you to read the output log to check the start address. If you need to start your code/data after the logical address of the ROM/RAM bank, you may output a NOP at the beginning (common values are 0, #4000,#8000, #C000 ...)
Quote from: zhulien on 11:54, 22 June 23Quote from: andycadley on 11:06, 22 June 23Quote from: zhulien on 10:30, 22 June 23Actually I have a heap across banks too, but it is not yet used by the c compiler, only used by assembler code. I plan to make it accessible to the c compiler though. Also virtual memory so that 128k users can have 4mb of vm.
I clearly must be missing something.
Let's say I have some data stored in a heap in some arbitrary bank of RAM, let's call it A. I want to pass a pointer to it to a function that ends up in bank B, this will manipulate the data and store a pointer to it in a linked list that is in bank C.
How can I possibly do that in assembly, without using 24-bit pointers and without some advance knowledge of where that bank is and without helper methods elsewhere in RAM to read from it?
You can do it with 16bit packed far addresses. The reason the data for a packed address needs to be aligned is because... they are packed. 4mb ram on a z80 is a lot and the packing of addresses makes programming easier with very little loss in the overall scheme.
back a few pages ago, you can already tell your generator to use macro and align directives...
we came full circle, i give up :-X
Quote from: zhulien on 11:54, 22 June 23Quote from: andycadley on 11:06, 22 June 23Quote from: zhulien on 10:30, 22 June 23Actually I have a heap across banks too, but it is not yet used by the c compiler, only used by assembler code. I plan to make it accessible to the c compiler though. Also virtual memory so that 128k users can have 4mb of vm.
I clearly must be missing something.
Let's say I have some data stored in a heap in some arbitrary bank of RAM, let's call it A. I want to pass a pointer to it to a function that ends up in bank B, this will manipulate the data and store a pointer to it in a linked list that is in bank C.
How can I possibly do that in assembly, without using 24-bit pointers and without some advance knowledge of where that bank is and without helper methods elsewhere in RAM to read from it?
You can do it with 16bit packed far addresses. The reason the data for a packed address needs to be aligned is because... they are packed. 4mb ram on a z80 is a lot and the packing of addresses makes programming easier with very little loss in the overall scheme.
But something has to unpack/repack that pointer every time it is used and (unlike in a high level language) you just cannot possibly know when that is in assembly language.
F.e.
I store a value in HL and then CALL some code that does
LD, A (HL)
INC A
LD (HL), A
LD (some_global_variable), HL
RET
What is the assembler supposed to do with this code? Is that value in HL a far pointer? What if I call the code from some other routine in the same bank? Does everything that accesses some_global_variable now have to change to accomodate the fact what is stored there might be a far pointer?
Quote from: andycadley on 12:10, 22 June 23Quote from: zhulien on 11:54, 22 June 23Quote from: andycadley on 11:06, 22 June 23Quote from: zhulien on 10:30, 22 June 23Actually I have a heap across banks too, but it is not yet used by the c compiler, only used by assembler code. I plan to make it accessible to the c compiler though. Also virtual memory so that 128k users can have 4mb of vm.
I clearly must be missing something.
Let's say I have some data stored in a heap in some arbitrary bank of RAM, let's call it A. I want to pass a pointer to it to a function that ends up in bank B, this will manipulate the data and store a pointer to it in a linked list that is in bank C.
How can I possibly do that in assembly, without using 24-bit pointers and without some advance knowledge of where that bank is and without helper methods elsewhere in RAM to read from it?
You can do it with 16bit packed far addresses. The reason the data for a packed address needs to be aligned is because... they are packed. 4mb ram on a z80 is a lot and the packing of addresses makes programming easier with very little loss in the overall scheme.
But something has to unpack/repack that pointer every time it is used and (unlike in a high level language) you just cannot possibly know when that is in assembly language.
F.e.
I store a value in HL and then CALL some code that does
LD, A (HL)
INC A
LD (HL), A
LD (some_global_variable), HL
RET
What is the assembler supposed to do with this code? Is that value in HL a far pointer? What if I call the code from some other routine in the same bank? Does everything that accesses some_global_variable now have to change to accomodate the fact what is stored there might be a far pointer?
Of course it is a near pointer. There is no difficulty in coding a multibabked program from the point of view,, I am not saying to not consider anything to do with addressing, but when assembling it would be nice if we could assemble a program eg that is very large and have the assembler work out the hard bit which is.. how many functions fit in a bank before resetting org for the next bank and identifying the cross bank calls and where so, substitute them for a defined macro. If totally handcoding assembly the benefit is still there but if a high level language is generating assembly rather than machine code natively, then it is a lot harder to know what is going in each bank.
For now even if I manually changed org to previous addresses I got warnings or errors so not sure what is going on there.
I will experiment more along the lines of...
Manually setting or to 4000h, at multiple locations in the code, followed by 4000h, $ ???
Maybe I can make the assembler warn me if it exceeds 7fffh but then I have to manually fix it to make things fit, manually change every far call... so much for a 2 second assembly process from c (for example). as I will need to do that every time I compile / assemble.
Unless of course, I modify the compiler to generate actual binary... losing the optimisation which is a 2nd optional program that analysts the asm before rasm gets it.
I think you're overlooking the big picture: Assembly Language has absolutely no concept of "a function" - everything is just code. You can jump into any point arbitrarily. You can manipulate things in ways that a high level language wouldn't ever do but the assembler has to be able to cope with, for example:
LD HL, r1
LD DE,r2
PUSH HL
PUSH DE
PUSH HL
PUSH HL
PUSH DE
PUSH DE
CALL r2
r1: INC A
RET NZ
r2: ADD A,A
JP Z, r1
RET
Is a completely valid bit of Z80 code that rasm has to be able to assemble. Where is the start and end of each "function"? Indeed how many functions are there? What do you expect rasm to do if it crosses a 16K boundary? What do you imagine the generated code looks like?
What you want is a linker, so that intermediate code can be generated without fixed addressing and it's code size known, so that your compiler can generate code as necessary and then the linker can figure out how to arrange the generated code optimally across multiple banks and fix up addressing to work (either using something like the firmware's RST scheme or by your code generator/linker agreeing a scheme of inserting NOPS where necessary to give fix up space.
function, I called it that, it's a label. Generated code would look almost the same whether catering for banked or not - only that rasm could detect which labels are called far or not and for far called ones in another pass, re-align them - it already knows the label address for everything, of course it does need another pass to recalculate after aligning far-called labels. It's not that hard - but from scratch it is a lot of work to create a brand new assembler and / or compiler. You are assuming I am trying to make rasm do something too high level - I am not, only identify which labels are referenced between banks, and substitute them for packed labels and / or macros which can call a banking function which handles the packed addresses. Your example code doesn't necessarily mean it has any far calls within it. We could even have a directive to wrap around code segments to indicate keep them together, don't put them across 2 banks. but... as mentioned, you can almost instantly flow from one bank to another anyway on CPC - it is very straight forward. You never created a linked list out of the banks and had the z80 automatically execute through all 512k of extended memory indefinitely? To do that, nop all the banks, at the end of each bank, stick the bank switching code to the next bank - don't forget the jump in the newly switched bank to jump to the start of the bank for that one's execution... For large code that is very valid, and yes, you can have global RAM heap and banked heap - which of course is not directly accessible.
In any case, if nobody has interest in such a feature than myself, that is fair enough.
The problem is you keep thinking of the process in terms of generated assembly code. But an assembler has to be able to cope with hand written code that can undermine assumptions such as "only labels get called" e.g.
LD HL, somelabel
LD DE, 256
ADD HL,DE
PUSH HL
RET
Which is essentially CALL somelabel+256.
Or
LD HL, somelabel
JP (HL)
Which is equivalent to the pseudocode:
LD HL, somelabel
CALL HL
RET
And that's just thinking about the entry point to a "function". Trying to determine where it might exit is, in the worst possible case, an NP complete problem
Expecting an assembler to somehow be able to divine the high level meaning of code is just not practical nor desirable in most cases. Every platform under the sun has faced and solved this problem already with an assembler capable of generating relocatable code and a linker.
I never mentioned only labels called. I mentioned labels that are referenced out of the current bank.
It is not hard to determine which labels are referenced from another bank and pack them.
Please think positive. If you don't believe the feature would be useful to you, I am not asking that it is a permanently enabled feature.
I am not going to ask this, but as an example... what if I asked it to support z80 and 6502 together so it works on both CPUs natively? Yep I have proven it can be done...
Given a file of assembly code how does RASM know where your "function" begins and ends? How does it know when one crosses into another bank?
What should RASM generate instead of the three bytes for a CALL instruction? Bearing in mind you only have three bytes, you can't move code again or assembling the code becomes a recursive function itself.
What should RASM generate instead of a JP instruction for a far pointer. What should RASM generate for a JR instruction that now refers to a far pointer.
I don't want to say but...
It's been 4 days of one-way dialogue
from my own experience i can say the generator would have been modified a long time ago to take account of those jumps :P
because from a generator point of view, it's easy and fast modifications. In fact, it's the easiest way to do
Quote from: andycadley on 08:57, 24 June 23Given a file of assembly code how does RASM know where your "function" begins and ends? How does it know when one crosses into another bank?
What should RASM generate instead of the three bytes for a CALL instruction? Bearing in mind you only have three bytes, you can't move code again or assembling the code becomes a recursive function itself.
What should RASM generate instead of a JP instruction for a far pointer. What should RASM generate for a JR instruction that now refers to a far pointer.
For me I would use rst 6 followed by the packed address for far calls. For far jumps i would probably throw a warning for coder to address them for this type of model. If directives were provided to wrap the entry and last statement for which must reside in a single bank, then no issues... as the coder would ensure that there are no jumps outside those groupings. Such groupings also don't need to conform to byte alignment within as they will always be local calls.
Maybe a minimal model could be...
Block align 256 (or 64) to start an aligned block
End block
The assembler would do 3 things only
1. Ensure a block if it cannot fit in the current bank goes to the next bank
2. Any calls to a far address not conditional calls, are changed to rst 6 followed by a packed address of the aligned block start
3. Any label references that are in another bank are packed
Assuming that (3) only refers to CALLs, i.e. a label reference to data in another bank just flat out fails, then what you have spec'd out is essentially a linker.
All you need is an assembler that can generate the necessary relocation information for fixups (I have no idea whether RASM is capable of that or not).
The linker can take care of inserted packed addresses and swapping CALL for RST as necessary (you'd probably have to use the other RSTs for conditional CALLs too) as these are trivial modifications. The advantage of a linker is that it could theoretically also rearrange functions in memory to fit better (though that's not strictly necessary).
Not only calls, also references to other far labels. If I make a table of assets that are all byte aligned in other banks, if the table is using labels I would expect them to be packed.
I agree a linker can do that, by rasm does so much already which is what makes it a good assembler.
Quote from: zhulien on 13:30, 24 June 23Not only calls, also references to other far labels. If I make a table of assets that are all byte aligned in other banks, if the table is using labels I would expect them to be packed.
But that's where it falls down. The minute you try to do it with anything that is potentially data and not just direct calls it won't work. Consider the code below:
#entered with A holding a table entry number
ADD A, A
LD L, A
LD H, HIGH(lookuptable)
JP (HL)
lookuptable:
DEFW routine1
DEFW routine2
DEFW routine3
If routine2 is in another bank, what's the assembler (or linker) supposed to do? If it packs the address, the code will break, if it doesn't then you'll jump into code that isn't paged in an get unintended results.
And that's before you even consider that one of the routines might need to be a far call and another a local call - leaving you in a situation where different things need to happen precisely because you've tried to hide what is going on under the hood.
Once you need that level of sophistication it's much easier to do it all in your generator. You know the code you're generating so can easily estimate the worst case memory it'll use (unless your optimizer is massively increasing code size but that's probably unlikely). And with a rough estimate, you can figure out where to place routines in banks, you don't need to know exact address etc, you just generate macros that will work it out once it actually gets assembled. And since you know the intent behind the generated code you can choose a suitable approach that will work in all the situations your code requires.
You must program in a different way than everyone else. Nothing falls over. It is a specific memory model with a specific behaviour that you code for in a specific way.
If you are using that model you will know how to use it and not code dumb code.
If you are looking up byte alighted packed addresses then you will likely use a routine somewhere that deals with packed addresses.
Since you obviously object to such features that you are not forced to use, that is bizarre.. instead of providing any constructive feedback on any improvements. You have only consistently said what won't work when it doesn't actually matter to the person who would love such a feature and how i would use them will work 100%
I needn't continue justifying why I would like such a feature. If rasm eventually gets this feature that will be awesome. But I will continue to use rasm without it.
I'm trying to help you come up with a mechanism that might actually work for what you want to do.
Transparently packing address during the assembly phase just doesn't work, there are too many cases where it isn't obvious what code you have to generate or where an assembler cannot possibly know whether a label is data or the entry point into a routine. If you knew they were packed addresses you could deal with it, as you say, but the whole point of your suggestion is that the assembler swaps them without you (or your code) ever knowing about it and fundamentally that is what breaks it.
As I said, it could work to some degree if you replace only CALL instructions with RSTs as part of a linking-style phase, although you still have to deal with data management manually and that's usually much more of a pain than code management. But you can't have tables of addresses etc because that requires treating the address as data and the program code has to understand what the data it would work on looks like.
I don't want data management handled automatically, only labels that are aligned in other banks to be packed. It makes it straight forward then to deal with data and/or logic anywhere in a 4mb or 16mb address space.
And I never said only entry point to a routine. Specifically I said labels that are referred to in another bank. It does not matter how they are referred... pack them. Only code substitute is CDxxxx, nothing more. Other code can generate incorrectly for all I care if misused... don't misuse it.
The packed address happens to essentially a handle to a bit of memory in 2 parts, 1 part a handle to a bank, 1 part a handle to a byte aligned address. Via both we will gain up to 16mb virtual memory on a standard 6128 at a reasonable speed... not very good speed but still possible on unexpanded 64k machine.
If I have to pad the last code bank with a ds #8000-$ so that the rest of the 16mb becomes a heap for assets and data, I am ok with that because... we are gaining almost 16mb for the small bit of 16k sacrifice... unless your entire program is smaller than 16k then why use the gigantic model...
But then why do you need the assembler to do anything, just use macros instead like:
macro PACKADDR bnk,addr
defw {bnk}, {addr} / 256
mend
; init cartridge output mode
buildcpr
bank 0
label1
jp label1
PACKADDR {bank}table,table
bank 1
ALIGN 256
table defb 0
because you know at this point that those addresses are always going to be in a FAR location, you have to because you have to write specific code to handle all the banking necessary to access them.
To be honest you can probably use rasms macros to do the substitution of a CALL instruction conditionally too in a similar fashion, although I'm not au-fait enough with the syntax to do it. Then the only issue is code overlapping from one bank to another which you can easily do by keeping track of the instructions you generate.
As mention in the very first chapter of the documentation, please DO NOT USE /256 to get high weight of an address or a value with Rasm
Rasm does correct rounding!
You must use a proper method for this
LD H,hi(myaddress)
or
LD H,myaddress>>8
Quote from: andycadley on 15:21, 25 June 23But then why do you need the assembler to do anything, just use macros instead like:
macro PACKADDR bnk,addr
defw {bnk}, {addr} / 256
mend
; init cartridge output mode
buildcpr
bank 0
label1
jp label1
PACKADDR {bank}table,table
bank 1
ALIGN 256
table defb 0
because you know at this point that those addresses are always going to be in a FAR location, you have to because you have to write specific code to handle all the banking necessary to access them.
To be honest you can probably use rasms macros to do the substitution of a CALL instruction conditionally too in a similar fashion, although I'm not au-fait enough with the syntax to do it. Then the only issue is code overlapping from one bank to another which you can easily do by keeping track of the instructions you generate.
Of course, it is easy if I am coding in assembly language. It is not at all straight forward if the assembly language was generated by a high level language.
Quote from: zhulien on 16:21, 25 June 23Quote from: andycadley on 15:21, 25 June 23But then why do you need the assembler to do anything, just use macros instead like:
macro PACKADDR bnk,addr
defw {bnk}, {addr} / 256
mend
; init cartridge output mode
buildcpr
bank 0
label1
jp label1
PACKADDR {bank}table,table
bank 1
ALIGN 256
table defb 0
because you know at this point that those addresses are always going to be in a FAR location, you have to because you have to write specific code to handle all the banking necessary to access them.
To be honest you can probably use rasms macros to do the substitution of a CALL instruction conditionally too in a similar fashion, although I'm not au-fait enough with the syntax to do it. Then the only issue is code overlapping from one bank to another which you can easily do by keeping track of the instructions you generate.
Of course, it is easy if I am coding in assembly language. It is not at all straight forward if the assembly language was generated by a high level language.
It's exactly the same. Generate the macros as part of the preamble to your output (since you can know up front what all of them will have to be) and then use the macros in place of generating the corresponding instructions.
Its not the same. To do it in a high level language means needing to calculate the size of generated code to know where banks overflow before we actually generate the assembly output. If you are handcoding assembler then you likely planned the placement of everything by hand to some degree already and only need to do it once. High level language do you expect someone to hand edit the assembler every time they press compile?
From our dialog, I suspect you don't understand the use and benefit.
Quote from: zhulien on 16:21, 25 June 2316bit packed far addresses
Can anyone tell me, what a
"16bit packed far addresses" is?
From my x86 asm time I know that far addresses are addresses >16bit (you had to specify the segment as well, which in total was already 32bit).
In SymbOS an address is specified by the 64k bank (currently 4bit, up to 16 banks) + 16bit address inside the bank, which is in total 20bit (1MB).
But what is a "16bit packed far address"??
Quote from: Prodatron on 22:27, 25 June 23Quote from: zhulien on 16:21, 25 June 2316bit packed far addresses
Can anyone tell me, what a
"16bit packed far addresses" is?
From my x86 asm time I know that far addresses are addresses >16bit (you had to specify the segment as well, which in total was already 32bit).
In SymbOS an address is specified by the 64k bank (currently 4bit, up to 16 banks) + 16bit address inside the bank, which is in total 20bit (1MB).
But what is a "16bit packed far address"??
If you know the pointer is 256 byte aligned, the bottom byte is always zero. So you can instead use that byte to store the bank number.
The firmware does similar things with ROM calls because it knows the address is never greater than #3fff
Quote from: zhulien on 19:22, 25 June 23Its not the same. To do it in a high level language means needing to calculate the size of generated code to know where banks overflow before we actually generate the assembly output. If you are handcoding assembler then you likely planned the placement of everything by hand to some degree already and only need to do it once. High level language do you expect someone to hand edit the assembler every time they press compile?
From our dialog, I suspect you don't understand the use and benefit.
You only need a very rough approximation because code blocks are going to be at least 256 byte aligned anyway and as long as you tend to overestimate it'll work out fine (with MBs of RAM you can afford to be generous). You can keep a worse case scenario count based on the instructions you generate, it doesn't need to be accurate enough to know actual addresses, just to get a feel for when you're close to the end of a bank. Heck you could just go with 3*instruction count and it'd probably do 90% of the time, especially if you leave some buffer space at the end of each bank.
@Prodatron in combination to the packed address schemes below, an unexpanded 6128 has 5 x 16k banks between 4000 and 7fff and we can page out the last used bank to have a fairly fast virtual memory scheme. Since only the last accessed ones are paged out, you effectively have a minimum of 64k always paged in based on how you control your program. You can quite regularly make fast interbank calls without disc paging as long as it isn't too random. I.e let's say of you have lots of game assets in 16mb ram. But you only need 64k of them per level. Of course you could load the data from disc in a traditional sense, but its a lot easier to code (debatably) if you can just call a function to grab the asset. More importantly is you can call code all over the place with reasonable performance.
Thanks God for symbiface and x-mass and m4.
OPTION 1: 16mb
address: xxxxxxxxyyyyyyyy
capacity: x = 256 x 64kb = 16mb
alignment: y = 64 x 256byte blocks per 16kb
stats:
64kb has 256 blocks
256kb has 1024 blocks
512kb has 2048 blocks
16mb has 65536 blocks
pros:
address fits within 16 bits
likely fast to translate due to 256 byte alignment
perfect fit for use with IX and IY registers
cons:
perhaps not enough blocks for certain types of applications
OPTION 2: 4mb
address: xxxxxxyyyyyyyyyy
capacity: x = 64 x 64kb = 4mb
alignment: y = 256 x 64byte blocks per 16kb
stats:
64kb has 1024 blocks
256kb has 4096 blocks
512kb has 8192 blocks
4mb has 65536 blocks
pros:
address fits within 16 bits
still works with IX and IY registers
lots of blocks for certain types of applications
cons:
slower to translate due to 64 byte alignment
Far address is the firmware guide terminology for an address that isn't paged in. I think there are rst instructions already catering for far address calls in ROM, so a similar technique can be used for RAM... just intelligent use of bits makes it more convenient in 16bits to cover the full memory map than eg... 24 bit addressing.
Just some other notes on Virtual Memory.
Banks with code or data that hasn't been modified do not need to be 'saved' when paged - only read. This involves keeping a dirty flag for banks that you set when modifying something in a bank.
As mentioned, an unexpanded 6128 has 5 x 16k banks in which 4 are cached at any one time out of a potential 65536 banks (the 65536 banks are packed into 8 bits because code blocks or data blocks are byte aligned)
If someone has 5128kb physical RAM added, 576kb total - then they have 33 most recently used banks cached at any one time.
If someone has 2048kb physical RAM added, 2112kb total - then they have 65 most recently used banks cached at any one time.
If someone has 4096kb physical RAM added, 4160kb total - then they have 129 most recently used banks cached at any one time.
Considering that some OSs like UZI perform complete 32kb swaps (at least it used to have no intelligence in the way it did it) and it still performed ok, this is actually a pretty good memory solution for CPC.
I am not expecting an influx of 16mb software for CPC - in fact likely none will ever appear. But... if someone does make it program that is several mb - it will seamlessly work on an unexpanded 6128 or a 4mb CPC.
Fun thing! Liked to read about the 16 bit far-address conventions. :)
Under FutureOS a 16 bit far address is actually consisting of 24 bit. 8 bits for the 16 KB RAM block to be used (256 * 16K = 4 MB). And then the 16 bit address of the RAM the Z80 has in direct access. Now the block only has 16 KB, not 64 KB. Therefore 48 KB remain untouched form banking.
This scheme I am building into PrimeOS which will be sure to work inside FutureOS which I have already started (but not tested). There should be no issues with FutureOS also "optionally" supporting the 4mb or 16mb virtual memory scheme too - If you'd like the VM banking functions I will send you them later, or if you prefer just the algorithm you can have that. Becase the most recent physical memory banks are in physical memory always except for or 1 bank that is always the last accessed (and next to be paged out), you can probably calculate performance i.e. to fill 16mb with NOPS - on a 128k system vs a 4mb expanded system. Or worst case, an unexpanded 464 which. In reality the difference just for this artificial NOP test isn't realistic except for example... loading a 16mb program where you will need to read and write every single 16kb block. But, for logic where you do repeated calls to different banks - the physical RAM hit is pretty high if the number of banks you are randomly calling is equal or less than the physical number of banks you have - there are programming restrictions / guidelines... e.g. don't trust an actual bank number - because we are using handles to banking, not real bank numbers. The ultimate purpose of this wasn't because we want 16mb RAM - although why not support that now for a future 16mb RAM expansion - but rather if we do make a 2mb or 4mb program, "it will still work (not necessarily fast) on an unexpanded 464 without modification" and "with reasonable speed on an unexpanded 6128".
download link https://github.com/EdouardBERGE/rasm/releases/tag/v2.0
New release Rasm v2.0 - 2023 Blue Hedgehog
What? Less than a month since two releases?
Yeah, sorry, but there was a huge rework and enhancement on dynamic LZ sections
You can now overflow the 64K memory space allocated IF YOU SQUEEZE enough your data to fit the 64K at the end ^_^
You may jump on another crunched section from anywhere if the destination is not 'in place', i mean, with a relocated ORG like "ORG #A000,$"
As usual, new features use the unlimited design, you may overflow as much as you want in the memory
As usual, the feature is already documented
Enjoy!
Note : There is also new AY conversion value, expect some audio changes
MacOS binaries & Windows binaries on github
Yes, that LZX0/LZCLOSE feature is insane, first time I'm seeing this in an assembler, thanks a lot Roudoudou!!!! :-*
Hi,
I've noticed in the binary generated with last release (2.1.5) some zeros are added before metastructs
buildsna
bankset 0
org #4000
run $
struct COORD
x db #77
y db #78
endstruct
struct COORD obj_coord, 5
struct st1
ch1 defw #0201
ch2 defb #03
endstruct
struct metast1
struct st1 pr1
struct st1 pr2
endstruct
struct metast1 bigst
ld hl,bigst.pr2.ch1
ld a,(hl)
ld a,(ix+metast1.pr2.ch1)
;; Output before 2.1.5:
;; 77 78 77 78 77 78 77 78 77 78 01 02 03 01 02 03 21 0D 40 7E DD 7E 03
;; Output with 2.1.5:
;; 77 78 77 78 77 78 77 78 77 78 00 00 01 02 03 00 00 01 02 03 21 0D 40 7E DD 7E 03
Quote from: isidoro on 18:41, 06 January 24Hi,
I've noticed in the binary generated with last release (2.1.5) some zeros are added before metastructs
thanks, i commited a fix + autotest
will publish another subversion soon
Quote from: roudoudou on 20:15, 06 January 24Quote from: isidoro on 18:41, 06 January 24Hi,
I've noticed in the binary generated with last release (2.1.5) some zeros are added before metastructs
thanks, i commited a fix + autotest
will publish another subversion soon
Thanks for your work, your assembler is amazing!!
Hi again,
One question, is there any way to insert data into struct when creating instances?
E.g., this code creates 4 instances of DIRTY_RECT, each one points to different GFX, how could I set GFX pointer of each instance?
struct COORD
x db #00
y db #00
endstruct
struct DIRTY_RECT
struct COORD screen
gfx_pointer dw
endstruct
struct DIRTY_RECT DIRTY_RECT_NINJA
;;db #00, #00
;;dw GFX_DIRTY_RECT_NINJA
struct DIRTY_RECT DIRTY_RECT_NINJA_WEAPON
;;db #00, #00
;;dw GFX_DIRTY_RECT_NINJA_WEAPON
struct DIRTY_RECT DIRTY_RECT_ENEMY
;;db #00, #00
;;dw GFX_DIRTY_RECT_ENEMY
struct DIRTY_RECT DIRTY_RECT_ENEMY_WEAPON
;;db #00, #00
;;dw GFX_DIRTY_RECT_ENEMY_WEAPON
Is there any way to fill data in struct instances?
Quote from: isidoro on 20:54, 11 January 24Hi again,
One question, is there any way to insert data into struct when creating instances?
Is there any way to fill data in struct instances?
it's a project I've been planning for a long time, but I still haven't decided how I'm going to do it. So... It's planned.
Ok, meanwhile can write data in emulator's assembler.
Thanks
Quote from: roudoudou on 08:27, 12 January 24Quote from: isidoro on 20:54, 11 January 24Hi again,
One question, is there any way to insert data into struct when creating instances?
Is there any way to fill data in struct instances?
it's a project I've been planning for a long time, but I still haven't decided how I'm going to do it. So... It's planned.
If it can help you to see what to do, or what not to do, on the syntax side, here is how I handle it on basm:
- https://github.com/cpcsdk/rust.cpclib/blob/master/cpclib-basm/tests/asm/good_struct.asm
- https://github.com/cpcsdk/rust.cpclib/blob/master/cpclib-basm/tests/asm/good_struct2.asm
- https://github.com/cpcsdk/rust.cpclib/blob/master/cpclib-basm/tests/asm/good_struct_no_default.asm
New release v2.2 Valentine
https://github.com/EdouardBERGE/rasm/releases/tag/v2.2
Important version because RASM and ACE were sharing the same wrong RLE encoding/decoding
No Impact for people using ACE & RASM only
But when sharing from other Emulator to ACE or importing from other Emulators to Rasm, you could have trouble with V3 version
bugfix Snapshot RLE encodingadd new math function pow2 to get fractionnal power of 2documentation updated
Developpers using ACE-DL must get new Valentine release http://www.roudoudou.com/ACE-DL/
Hi, I've just tested v2.2, and I get an output of 0kb .sna file. I build my project with:
buildsna
bankset 0
org CODE_INI
run entry_point
And this VSCode tasks.json:
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"command": "bin\\.\\rasm \"${file}\" -ob \"output\\${fileBasenameNoExtension}.bin\" -oi \"output\\${fileBasenameNoExtension}.sna\"
},
{
"label": "test",
"type": "shell",
"command": "bin\\.\\rasm \"${file}\" -ob \"output\\${fileBasenameNoExtension}.bin\" && AceDL\\.\\AceDL.exe"
}
]
}
Quote from: isidoro on 18:46, 13 February 24Hi, I've just tested v2.2, and I get an output of 0kb .sna file. I build my project with:
buildsna
bankset 0
org CODE_INI
run entry_point
rasm wont ouput anything if there is no code
about VS i dont know how its working, maybe you should try command line first
Quote from: roudoudou on 20:37, 13 February 24Quote from: isidoro on 18:46, 13 February 24Hi, I've just tested v2.2, and I get an output of 0kb .sna file. I build my project with:
buildsna
bankset 0
org CODE_INI
run entry_point
rasm wont ouput anything if there is no code
about VS i dont know how its working, maybe you should try command line first
Excuse me, my English is not very good, maybe I have not expained it enough.
There is code in my project, I've only posted that related to rasm. With previous version my code generates the .sna correctly, I've only replaced rasm executable with the new one. Compiler outputs messages of inserting data, truncating values, and creates the sna file, but the file is empty. I've tried with:
.\rasm.exe "project.asm"
With the same result.
Maybe I'm missing something ...
Quote from: isidoro on 21:01, 13 February 24I've tried with:
.\rasm.exe "project.asm"
With the same result.
Maybe I'm missing something ...
i guess there is some output in the console right? this may help
for example, something like
Pre-processing [minimal.sna]
Assembling
Write snapshot v3 file minimal.sna
WriteSNA bank 0,1,2,3 packed
Total 4 banks (64K)
oh, i got it, one special case missed with that E5 byte...
will make a proper test and fix it...
anyway that does not explain that zero byte file...
EDIT; just runned some defb #E5,#00,#E5,#E5,#00,#E5,#E5,#E5 then it crashed...
fix this tonight ;)
sorry for this, should have done this Autotest before... (doing this all day long, what a shame!)
new release, bugfixing the bugfix ^_^ https://github.com/EdouardBERGE/rasm/releases/tag/v2.2.1
Quote from: roudoudou on 21:25, 13 February 24sorry for this, should have done this Autotest before... (doing this all day long, what a shame!)
new release, bugfixing the bugfix ^_^ https://github.com/EdouardBERGE/rasm/releases/tag/v2.2.1
Now it's working fine :D , thanks!!
New release https://github.com/EdouardBERGE/rasm/releases/tag/v2.2.2
Introducing new directive HFE for HFE floppy authoring (commands will be enriched in the future)
Documentation draft about that directive with examples http://rasm.wikidot.com/directives:hfe-creator
Great
This is not clear in the documentation: HFE directive does not allow saving files on disc ? It is just for low level stuffs ?
On an ergonomic side, EDSK and HFE seem to have similar features named differently or working differently. If I'm wrong, it's perfect, but if I'm not wrong some harmonization would be probably useful.
HFE Close will save the HFE
Probably some harmonization in a higher level (for example saving sectors in a row from Rasm memory), it mazy evolve
note: HFE is supposed to be used for low level tricks (protections, trackload, FDC experimentations)
I wrongly wrote my question: when saving, I had in mind "Amsdos file saving", not saving the content of the hfe file
But ok; you answer anyway: it is for low level stuff ;)
Then I could suggest the SAVE command to consider the DSK parameter as a synonym of DISC or HFE and use the filetype extension to really know if it is a dsk or hfe.
This will allow you ta save on dsk or hfe without having to change the current syntax.
This ill help to push out the dsk format in favor of hfe too ;)
ps: as time flies, I really hate more and more the standard way to handle directives in most z80 assemblers, this is really not ergonomic
Will think about how we can mix syntax, thanks
Quote from: krusty_benediction on 23:11, 21 March 24[...]
ps: as time flies, I really hate more and more the standard way to handle directives in most z80 assemblers, this is really not ergonomic
Although this is a bit off-topic for this thread, I'm really curious about this topic. In syntax and functionality there is a big gap between an (old 8-bit) assembler language where the programmer has to think many levels in advance to avoid several pitfalls, compared to a modern high level language that does its best to guess what the programmer means by something close to simplified pseudo-code.
What do you mean with the "standard way to handle directives"? And are there ideas for improvement?
Since 1986 I had the feeling that there must be something between Assembler and e.g. Logo. From functionality this would be C, but I do not like its syntax, and some design choices were also made to simplify the compiler.
Quote from: lightforce6128 on 04:25, 26 March 24Quote from: krusty_benediction on 23:11, 21 March 24[...]
ps: as time flies, I really hate more and more the standard way to handle directives in most z80 assemblers, this is really not ergonomic
Although this is a bit off-topic for this thread, I'm really curious about this topic. In syntax and functionality there is a big gap between an (old 8-bit) assembler language where the programmer has to think many levels in advance to avoid several pitfalls, compared to a modern high level language that does its best to guess what the programmer means by something close to simplified pseudo-code.
What do you mean with the "standard way to handle directives"? And are there ideas for improvement?
Since 1986 I had the feeling that there must be something between Assembler and e.g. Logo. From functionality this would be C, but I do not like its syntax, and some design choices were also made to simplify the compiler.
I've just created a new topic to not pollute rasm one https://www.cpcwiki.eu/forum/programming/some-thoughts-for-modern-assembler-in-amstrad-world/new/#new