This is the most important feature. It means that you can compile your assembly into an "object file" and then combine object files into a binary later. For example, let's say I do this:
main:
call subroutine
retI can run this file (as-is) through scas like so:
scas -c -o main.o main.asmThis will produce "main.o" without errors. However, if I try this:
scas -o main.bin main.oIt will give the following error:
main.asm:2:0: error #5: Unknown symbol
call subroutineThis works even if you delete main.asm. scas includes a source map in object files. You can see it with scasdump:
sircmpwn@homura /t/tmp.kU6Nr9sNGD> scasdump -s -r -c main.o
Area '_CODE'
Source file 'main.asm'
[0x0000:03] main.asm main:
[0x0000:03] main.asm:2 call subroutine
[0x0003:01] main.asm:3 ret
Symbols defined:
'main' == 0x00000000 (Label)
Unresolved references:
[0x0001] 'subroutine'This behaves similarly to
objdump on Unix systems. I can now write another small file:
subroutine:
ld hl, 0
retAnd compile it like so:
scas -c -o subroutine.o subroutine.asmThis produces another object file, subroutine.o. You can now run this without errors:
scas -o main.bin main.o subroutine.oThis "links" together the two object files. Since subroutine.o defines "subroutine", the reference from main.o works and it's all good. Of course, this is all optional. The following works, too:
scas -o main.bin main.asm subroutine.asmOr even this:
scas -o main.bin main.asm subroutine.oOr just this:
scas main.asmWhich assumes you want the output file to be main.bin.
This is all important because it lets you compile each of your files and then link them all separately. This means that if main.asm changed but subroutine.asm didn't, only main.o would need to be recompiled and then it could be linked against the old subroutine.o. For smaller projects, this isn't a big deal, but it saves a lot of time on larger ones. You could also swap out a different version of subroutine.o so long as it also provided the "subroutine" label by simply linking against a different object file. This gets even cooler when you start thinking about static linking. KnightOS has a
libc that provides a bunch of common functionality. You can link against it and scas will optimize out the things you don't use. This lets you build libraries that are compiled into your programs rather than used separately. As an added bonus, you can choose to use the explicit export option. That way, you can write subroutine.asm like so:
.export subroutine
subroutine:
ld hl, 0
ret
main:
retWhen you link against main.o, you won't get an error for duplicate labels. This is because only "subroutine" is exported from this object. This lets you reuse common label names and write each file as its own module without worrying about conflicting with other modules. If you want to get really crazy, you can also use the explicit import flag, which would make you change main.asm to this...
.import subroutine
main:
call subroutine
ret...to avoid a compiler error. This is starting to get really similar to how C works, right? scas uses a very similar design to modern toolchains.