I'm writing a multi-modular assembly project with MASM for DOS. In particular, I'm trying to do a very simple DOS-like OS,
I have several segments defined like this;
fileseg segment byte public 'code'
fileseg ends
memseg segment byte public 'code'
memseg ends
diskseg segment byte public 'code'
diskseg ends
bootseg segment byte public 'code'
bootseg ends
As you see all of them are byte-aligned (design decision). Also I have a cseg group that encompasses all of the above segments
cseg group fileseg, memseg, diskseg, bootseg, ...
so when I want to reference a public label, no matter if it's defined in a different segment, i will do something like:
assume ds:cseg, es:cseg, ss:cseg
mov si, offset label_in_this_segment
mov bx, offset label_in_another_segment
and it'll get the 'global' offset within cseg, which is right. But the problem arises when you write some code that needs to be executed in a fixed location, as a boot sector, that executes at 0000:7C00h (in my case at 07C0:0)
so I wrote it like this:
bootseg segment byte public 'code'
; Want all data references to be relative to this segment, not CSEG
assume ds:bootseg
boot_start::
jmp start
boot_data t_bootloader_data <>
start:
; make IP point to 0000h
mov ax, 07C0h
push ax
mov ax, offset ds:real_start ; "BAD" offset
push ax
retf
real_start:
mov ax, cs
mov ds, ax
...
I put "BAD" in quotes because MASM is actually doing it right, since bootseg is also part of the cseg
group (because boot_data
it's referenced from some other segments), so the linker marks "real_start" as relocatable.
So the question would be: how do I tell the assembler that I wantreal_start
to be offseted from bootseg
itself?
I tried some tricks that work, like making bootseg
be the first segment defined, or making it paragraph-aligned, but these seem somewhat hacky to me.
I also tried to put bootseg
out of the cseg group but again, I need boot_data
to be referenced from other segments before the boot sector is written to disk.