Making reusable code in assembler
Posted: Wed Jan 18, 2023 1:45 am
I'm working on some display routines which handle scrolling and whatnot.
I want to make the code as reusable as possible, so I've used constants to allow values such as the screen dimensions to be specified, e.g.
This is fine, but means I am having to use "generic" functions to do multiplications, which could be coded more efficiently
e.g. instead of using something such as this function (renamed HL_equals_HxE below), which clocks in around 249 Ts minimum...
...it would be nice to be able to use the following, which is much more efficient at just 87 Ts
My first thought was to create a config file, and specify which file we want to use there (if any ) to override the multiplication, e.g.
In this case, 'better_multiply.asm' would contain the optimised snippet from above.
Then adjust the code:
Sadly, the pasmo assembler doesn't like this. The manual states that "the use of IF directives to conditionally include different files is not allowed"
So that leads me to the questions:
1. Are there any assemblers which do support conditional INCLUDEing of files in a manner similar to that described above?
I'm not too fussed if the filename can not be specified by the author, i.e. "you must place your optimised code in OverrideFile.asm and activate in config.asm by specifying ActivateOverrideFile EQU 1" - though it'd be "nice to have" such flexibility if available. The code would be bundled with examples which can be tweaked to suit... and the "generic function method" is always available as a default/failsafe option if the author isn't confident making the optimisations.
In short, I want it to be tweakable without affecting the original code.
2. Portability implications
I was looking at other assemblers and took a brief look at sjasmplus, and realised that there is syntax which differ between assemblers...
sjasmplus did not like the if/else/endif statements, nor REPT/ENDM directives, and treats them as labels.
It seems you have to write code which works with your assembler of choice... or are there common tricks I am missing?
It would be nice if others could have access to the finished code without having to modify it, but I'm guessing this is not gonna happen!![Neutral :|](./images/smilies/icon_neutral.gif)
I want to make the code as reusable as possible, so I've used constants to allow values such as the screen dimensions to be specified, e.g.
Code: Select all
buffer_width_in_cells EQU 24
buffer_width_in_cells EQU 24
e.g. instead of using something such as this function (renamed HL_equals_HxE below), which clocks in around 249 Ts minimum...
Code: Select all
; HL = bg_attr_addr + (top_offset * buffer_width_in_cells)
; Use HL_equals_HxE
LD A, (top_offset)
LD H, A
LD E, buffer_width_in_cells
CALL HL_equals_HxE ; 187 Ts - 238 Ts ... see link above for source!
LD DE, bg_attr_addr
ADD HL, DE
Code: Select all
LD A, (top_offset) ; A = top_offset (0-23)
ADD A, A ; x2, max 46
ADD A, A ; x4, max 92
ADD A, A ; x8, max 184… over 127, so switch to 16 bit shift
LD H, 0
LD L, A ; HL = x8
LD D, H
LD E, L ; DE = x8
ADD HL, HL ; x16
ADD HL, DE ; x24
LD DE, bg_attr_addr
ADD HL, DE
Code: Select all
optimised_include EQU 'better_multiply.asm'
Then adjust the code:
Code: Select all
; HL = bg_attr_addr + (top_offset * buffer_width_in_cells)
if optimised_include
INCLUDE optimised_include ; 'better_multiply.asm' in this case!
else
; Use HL_equals_HxE
LD A, (top_offset)
LD H, A
LD E, buffer_width_in_cells
CALL HL_equals_HxE
LD DE, bg_attr_addr
ADD HL, DE
endif
![Sad :(](./images/smilies/icon_e_sad.gif)
So that leads me to the questions:
1. Are there any assemblers which do support conditional INCLUDEing of files in a manner similar to that described above?
I'm not too fussed if the filename can not be specified by the author, i.e. "you must place your optimised code in OverrideFile.asm and activate in config.asm by specifying ActivateOverrideFile EQU 1" - though it'd be "nice to have" such flexibility if available. The code would be bundled with examples which can be tweaked to suit... and the "generic function method" is always available as a default/failsafe option if the author isn't confident making the optimisations.
In short, I want it to be tweakable without affecting the original code.
2. Portability implications
I was looking at other assemblers and took a brief look at sjasmplus, and realised that there is syntax which differ between assemblers...
sjasmplus did not like the if/else/endif statements, nor REPT/ENDM directives, and treats them as labels.
It seems you have to write code which works with your assembler of choice... or are there common tricks I am missing?
It would be nice if others could have access to the finished code without having to modify it, but I'm guessing this is not gonna happen!
![Neutral :|](./images/smilies/icon_neutral.gif)