I am assembling a program with NASM to fit in the boot sector (512 bytes max).
e.g. nasm -f bin boot.asm -o boot.bin
The last two lines of the program pad the remaining space with 0 and add the magic bytes:
times 510 - ($-$$) db 0 ; Pad the remaining of the first 510 bytes with 0
dw 0xAA55 ; Magic bytes required at end of boot sector
The outputted boot.bin
file is always 512 bytes (expected), so I cannot trivially look at the size of boot.bin
to get the size of the meaningful (non-padding and non-magic bytes) instructions.
I imagine it would work to print ($-$$)
at assembly time (similar to #warning
or #pragma message
for gcc), but I cannot find any way to print at NASM assembly time.
Is there a clean or straightforward way to know the size of the instructions before padding?
It would be nice to avoid hacky methods like printing at runtime or searching backwards through boot.bin
looking for a non-zero value.
You can use %assign
to evaluate a numeric expression at assemble time. (Each assembly pass also uses the preprocessor. This is how you can do limited arithmetic on labels using the preprocessor.) Then use %warning
to display an assemble time message. The only downside is that it'll display "as a warning", but it is assembly time output. Quoting the manual:
[...] %warning issues a warning, but allows assembly to continue:
[...]
It is optional for the message string after %error, %warning or %fatal to be quoted. If it is not, then single-line macros are expanded in it, which can be used to display more information to the user.
In my boot sector loaders I do this:
available:
_fill 508,38,start
signatures:
dw 0
; 2-byte magic bootsector signature
dw 0AA55h
%assign num signatures-available
%assign fatbits 12
%if _FAT16
%assign fatbits 16
%endif
%warning FAT%[fatbits]: num bytes still available.
%endif
end:
_fill
is from the macro collection. Refer to my question about the zeros for the meaning of the first dw
here.
Example output:
boot.asm:1600: warning: FAT12: 10 bytes still available. [-w+user]
You could put a label before the padding and do size: dw $-$$
to store a size in the bootloader that you could look at in an asm listing or hexdump. But that takes up 2 bytes.
nasm -fbin foo.asm -l /dev/stdout | less
will display a listing of address | hexdump | source line, making it very easy to see where the time ... db 0
starts, and to the integer you put into the dw
. You can see an example of that format in a code-golf answer of mine for example.
Or you can simply comment out the times 510 - ($-$$) db 0
/ dw 0xaa55
padding and look at the file size!
If you're close to the limit, leave it commented out while optimizing for code size until you have something you think should fit and work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With