When it's generating the code the assembler treats all labels as offsets from the start address, with the start address being defined by the ORG statement (Which, as mentioned, is assumed to be ORG 0x0 if not present in the code).
So if, for the sake of example, I have something like this:
Code: Select all
ORG 0x0
mov %DS, %AX
ljmp $SOMESEG, $mylabel
mylabel:
Now I happen to know that 'mov %DS, %AX' is encoded as 2 bytes, and that a long jump in real-mode is encoded as 5 bytes. So the assembler will treat the label 'mylabel' as having a value of 0x7 because the instruction following the label 'mylabel' will have an offset of 0x7 bytes into the file and the start address is 0x0 (Because I used ORG 0x0).
What this means is that the instruction 'ljmp $SOMESEG, $mylabel' will load CS with SOMESEG, and IP with 0x7. The effect is to jump to the address SOMESEG:0x7.
Now let us say that my little example is loaded to 0x07C0:0x0000 (As Bootsect is).
Let us assume for a moment that I set SOMESEG to be 0x07c0.
When the instruction 'ljmp $SOMESEG, $mylabel' is reached the processor will jump to 0x07c0:0x0007. This will be the address of the instruction following the label 'mylabel'.
Now let's say I have made a copy of my program at 0x9000:0x0000.
If I set SOMESEG to be 0x9000 then when the instruction 'ljmp $SOMESEG, $mylabel' is reached the processor will jump to 0x9000:0x0007. This will be the address of the instruction following the label 'mylabel'
in the copy of my program.
I can switch between the original and copy as many times as I like using 'ljmp' to change the code segment and have everything work because the labels are just offsets within the segment and our assumption that the offset for the start of the program is 0x0 (ORG 0x0) is true for both the copy and the original.
What I
couldn't do is make a copy of my program at 0x9000:0x0100 and try to do the same thing. Because a long jump is encoded as an absolute address (Not relative) my 'ljmp $SOMESEG, $mylabel' would still be jumping to 0x9000:0x0007 which would no longer be the instruction following 'mylabel' in the copy. In this case my assumption of ORG 0x0 is not true for the copy of the program. The start address of the copy would actually be 0x100 and I would have to adjust the code to compensate.
***
Back to bootsect.S
It should be pretty obvious now what's going on, but I'll run through it anyway.
Ok, I'm gonna run through this very very slowly to try and clear it up.
Code: Select all
movw $BOOTSEG, %ax
movw %ax, %ds
movw $INITSEG, %ax
movw %ax, %es
movw $256, %cx
subw %si, %si
subw %di, %di
cld
rep
movsw
First thing to realise is that there is no ORG statement at the start of this code. Because there is no ORG statement the assembler assumes ORG 0x0.
DS is loaded with BOOTSEG (0x7c0)
ES is loaded with INITSEG (Usually 0x9000)
SI and DI are set to 0, direction flag is cleared.
BIOS loads the bootsector to 0x7c0:0x0000 and executes the first instruction. At this point CS:IP = 0x7c0:0x0000 (Or an equivalent address).
The bootsector then copies 512 bytes from 0xBOOTSEG:0x0000 to 0xINITSEG:0x0000. This has the effect of making a copy of itself which starts at 0xINITSEG:0x0000.
Because the start offset of both the orginal and copy is 0x0 our ORG 0x0 assumption is correct for both the original and the copy. So the label offsets will be correct in both.
CS is
still BOOTSEG at this point.
The code then makes a long jump to change CS into INITSEG.
After the jump CS = $INITSEG and ip = $go and execution continues with the instruction following 'go' in the copy.
***
Hopefully that makes sense to you.