Page 1 of 1
Realocate code during execution (chain loading)
Posted: Thu Feb 26, 2009 1:28 pm
by mangaluve
How do I reallocate some code during execution? I'm writing a boot sector that will use chain loading. So the first thing I do in my boot sector is to load itself to another location (I do this by reading it from disk again, but I assume there is a good way of moving 512 bytes without having to re-read them?). Now I would like to continue the execution of my code, but on the new location. So I have something like
[BITS 16]
[ORG 0x7C00]
; Load this code to for instance 0x6000.. this I know how to do
; Here I want to jump to the corresponding place in the code when the code is loaded to 0x6000
bootsector_continue:
; Do something else
How do I do this? Because my boot sectors assumes that it starts on 0x7C00, but it will no longer be there after the relocation (and I can't have another [ORD 0x6000] right?)
Re: Realocate code during execution (chain loading)
Posted: Thu Feb 26, 2009 2:47 pm
by gzaloprgm
How do I reallocate some code during execution? I'm writing a boot sector that will use chain loading. So the first thing I do in my boot sector is to load itself to another location (I do this by reading it from disk again, but I assume there is a good way of moving 512 bytes without having to re-read them?). Now I would like to continue the execution of my code, but on the new location. So I have something like
You can use
rep movsb to copy some amount of bytes into one location to another:
Rep movsd ;Copies CX bytes from DS:SI to ES:DI
[BITS 16]
[ORG 0x7C00]
; Load this code to for instance 0x6000.. this I know how to do
; Here I want to jump to the corresponding place in the code when the code is loaded to 0x6000
bootsector_continue:
; Do something else
How do I do this? Because my boot sectors assumes that it starts on 0x7C00, but it will no longer be there after the relocation (and I can't have another [ORD 0x6000] right?)
I think you should use ORG 0 and use segments (so bootsector_continue is in 0x600:bootsector_continue)
Cheers,
Gonzalo
Re: Realocate code during execution (chain loading)
Posted: Thu Feb 26, 2009 3:41 pm
by mangaluve
Thanks!
But can I put [ORG 0] just anywhere in my code? Or how do you mean? I know about protected mode and segments but I haven't used it enough to know exactly what you mean..
Re: Realocate code during execution (chain loading)
Posted: Thu Feb 26, 2009 6:27 pm
by JohnnyTheDon
Put it in the beginning, then use something like
Code: Select all
[ORG 0]
jmp 07C0h:entry ; Set CS to a known value
entry:
mov ax, cs
mov ds, ax ; Make DS the same as the code segment
mov ax, 0600h
mov es, ax ; Make ES the destination segment
xor di,di
xor si,si
mov cx, 512 ; Moving 512 bytes of code
cld
rep movsb
jmp 0600h:postmove ; jump into newly written code
postmove:
mov ax, cs ; Set all segments to code segment
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
These are real mode segments, not pmode segments. Protected mode segments are offsets into a GDT, and this code doesn't enter protected mode or load a GDT. You can still do that later though
Re: Realocate code during execution (chain loading)
Posted: Fri Feb 27, 2009 3:14 am
by mangaluve
Thanks a lot! But usually when you write [ORG 0x7C00], which instructions are there that needs to know where in memory the program is? Isn't most jump-instructions near jumps and so on.
Secondly, you chose to move the code to 0600h and not 06000h, why is that? When you do "jmp 0x600h:postmove", you jump to address 0x6000h + postmove, right? So shouldnt it be loaded into 0x6000h?
Re: Realocate code during execution (chain loading)
Posted: Fri Feb 27, 2009 5:27 am
by Combuster
No, addressing is different in
Real Mode
Re: Realocate code during execution (chain loading)
Posted: Fri Feb 27, 2009 11:54 am
by Ready4Dis
Yes, you can put an org statement anywhere. You can either set the code and data segments as suggested, or just use [org 0x6000] and not worry about changing cs,ds,es,fs,gs (as long as it won't overflow the 64k page boundary). It is limited to 0x6000 -> 0xffff, so you will have 0x10000-0x6000 = 0xA000, or 40,960 bytes to play with if you don't use segmentation, if you do use segmentation, you will have an entire 64k to play with. (Either should suffice for a first stage boot loader!) My master boot record replacement does this, it copies itself out of the way, then copies in the first sector of the partition you chose to the location 0x7c00 (hence having to move itself out of the way).
Please read up a bit on segmentation, it will explain why it appears he's loading it at 0x600 rather than 0x6000, since he is setting ax = 0x600, and es = ax... this sets the segment register to 0x600. In real mode, it uses this segment base (0x600) and di (es:di pair), so that means it will actually load to 0x6000 (es << 4) + di.
Ok, I was going to comment on the code, but here is the code how I would do it
.
Code: Select all
[bits 16]
[org 0x7c00]
jmp 0x00:entry ;Set CS to a known value (0)
entry:
;Clear all segment registers so we need not touch them again!
xor ax, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
;From here on I don't play with segments anymore, keeps things simple, especially for people reading my code who aren't completely familiar with segmentation, and makes it easier to port to other platforms that don't support segmentation
cld
mov si, 0x7c00
mov di, 0x6000
mov cx, 512/4 ;Why do this one byte at a time, lets do a double word at a time
rep movsd ;This does the copy
jmp new_entry ; Jump to our new location :)
[org 0x6000] ;Reset our origin
new_entry:
;Finish what you wanted to out of the way now
Re: Realocate code during execution (chain loading)
Posted: Fri Feb 27, 2009 3:15 pm
by JohnnyTheDon
Ready4Dis wrote:Yes, you can put an org statement anywhere.
Not always.
NASM doesn't let you put a second ORG statement. Segments are probably a better way to do it, because you can relocate the code anywhere at runtime, and its not limited to the first 64kb.