When the code has grown big enough, it made sense to split it into several files. So I've split it into files which make sense together. How can it be done?
First, one must have define files. Akin to header files in C, these are used to define constants - such as SFR locations - and macros - such as SFR assignments.
These files are pure assembly files, and as it seems that ASXXXX is agnostic to file extension, I'll go with ASXXXX examples and call these "define.def" and "macro.def".
These are used in other assembly files using the .include directive, just like C preprocessor #include.
The cruedest way to get all my files together is to create a capital assembly file which includes all these files. Here is "semyon.asm" where it all goes together:
.module semyon ;Def file includes .include "define.def" .include "macro.def" ;Asm file includes .include "main.asm" .include "intv.asm" .include "inth.asm" .include "dseg.asm" .include "io.asm" .include "delay.asm" .include "pwm.asm"
The "include" directive just copies the included files into the caller file. Unsurprisingly, it gets assembled just as good as assembling it all in one file.
But now doing it properly
This approach is not good. The conceptual problem is that it's not doing what I intended - I didn't want it to simply copy and paste my code together, but to assemble it in pieces and then assign all the addresses and tie the hex file together.
The practical problem is that ASXXXX is not smart enough to trace bugs into the included files. A bug in "io.asm" will come out as a bug in "semyon.asm" in line 12, which is where the problematic file is included. It leaves you guessing where in that file the error has occurred, and I'm not masochistic enough for that.
Nope, the proper way mandates that I assemble each file independently. It makes sense to include all the ".def" files in each ".asm" file then, but some labels are cross referenced - for example, "main.asm" calls for functions from "io.asm". This can be solved by assembling all the files with global flags.
This is the makefile:
build:
as8051 -losga main.asm
as8051 -losga intv.asm
as8051 -losga inth.asm
as8051 -losga io.asm
as8051 -losga delay.asm
as8051 -losga dseg.asm
as8051 -losga pwm.asm
aslink -f semyon
packihx semyon.ihx > semyon.hex
The "los" flags are the old output files flags. The "g" and "a" flags make user-defined and undefined symbols global, respectively (see docs.). It means that the output files expect to assign these at linking time.
Linking
The linker is called aslink (sdld in the sdcc version) and is quite simple. It can get directives from a file, using the "-f" flag.
The directives are simply structured: Linker flags, output file name, list of input files, and the reminder of the flags, mostly link-time symbol value assignments.
My linking file "semyon.lnk" is looking like that:
-mxiu semyon main intv inth delay pwm dseg io -b CODE = 0x0090 -e
the -mxiu flags means generate map file, hex base, intel hex output, and update the list files, respectively. See more.
"semyon" is the name of the output file, the rest are the input files (extensions get ignored).
"-e" is end-of-file marker flag.
About the .area directive
The mysterious .area directive which bugged me makes sense now when multi-file code is concerned - the linker should know how to put the assembled files together, at what addresses and so on.
The "intv.asm" file, which includes the interrupt vectors, should be strictly located in predefined addresses using the ".org" directive. Thus the area it got, called INTV, must be defined ABS, which means that the addresses must be manually assigned.
Most of the code however goes in the CODE area, which got the REL flag. That means each file to whom this area was assigned will be concatenated upon the other files in that area, and the ".org" directive is prohibited.
However, the REL areas must begin somewhere. Originally I wanted it to be at 0x90, after all the interrupt vectors. I can assign this to REL areas in link time, using the "-b" flag:
-b CODE = 0x0090
The code links very well this way, and function exactly as if it was a one-filer.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.