I think that when the assembler output is pure binary, it is better to treat all labels as scalars. Moreover, I'd like to treat this as feature request. First, this will help to optimize code without using obscure label mathematics, the sample is here (first post):
http://forum.nasm.us/index.php?topic=656.0Second, sometimes it is needed to mangle with addresses to solve the task. The obvious examples are: GDT building at assembly time and FAT12 image creation (with files). Both tasks are easily solved with FASM since it has two very valuable features:
-
Treating labels as scalars when producing binary output.-
"Load/Store" directives that allow to get and save any calculated data at/from any location.Please look at the following code:
; Segment desciptor definition. Parameters: base, limit, attribs
%macro GDT_entry 3
.limit: dw (%2)&0FFFFh
.base_l: dw (%1)&0FFFFh
.base_m: db ((%1)>>16)&0FFh
.access: db (%3)&0FFh
.attribs: db (((%2)>>16)&0Fh) | (((%3)>>4)&0F0h)
.base_h: db ((%1)>>24)&0FFh
%endmacro
section .data
; GDT
align 16
gdt: GDT_entry 0, 0, 0 ; Null descriptor
gdt_tss: GDT_entry TSS, TSS.io_map-TSS-1, ATR_TSS ; TSS for task
section .bss
align 4
TSS: ; TSS definition for 386+
.link: resw 2 ; High word not used
.esp0: resd 1
.ss0: resw 2 ; High word not used
; Not interesting part of TSS is omitted
.io_map_addr: resw 1
.io_map: resb 8192 ; I/O map for TSS
You know that calculation of GDT entry is very confusing (thanks to Intel!). The arithmetics is done by macro above. The GDT entry for TSS must have the base address pointing to TSS entry. I can't write TSS-$$ to convert relocatable label to scalar in the sample above because the GDT and TSS are in different segments. This calculation is forbidden. One may suggest to place
TSSstart equ TSS-$$
right after TSS in the same segment and then use TSSstart instead of TSS. But this doesn't work because it gives WRONG result since the start of BSS segment ($$) is not 0, so the calculated address is not physical address of TSS in memory. SEG keyword is forbidden here by NASM since the output is binary.
The loading/storing not only helps to easily create FAT entries for files but allows to, for example, encrypt the parts of code in ASM controlled manner. Please check how this is done in FASM.
BTW, I don't like FASM. The NASM is the best assembler and I want it to be PERFECT
.