Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the total size of the NASM-assembled instructions in a boot sector?

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.

like image 849
Costava Avatar asked Sep 17 '25 02:09

Costava


2 Answers

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]
like image 63
ecm Avatar answered Sep 19 '25 20:09

ecm


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.

like image 29
Peter Cordes Avatar answered Sep 19 '25 19:09

Peter Cordes