Realocate code during execution (chain loading)

Programming, for all ages and all languages.
Post Reply
mangaluve
Member
Member
Posts: 110
Joined: Mon Feb 23, 2009 6:53 am

Realocate code during execution (chain loading)

Post 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?)
User avatar
gzaloprgm
Member
Member
Posts: 141
Joined: Sun Sep 23, 2007 4:53 pm
Location: Buenos Aires, Argentina
Contact:

Re: Realocate code during execution (chain loading)

Post 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
Visit https://gzalo.com : my web site with electronic circuits, articles, schematics, pcb, calculators, and other things related to electronics.
mangaluve
Member
Member
Posts: 110
Joined: Mon Feb 23, 2009 6:53 am

Re: Realocate code during execution (chain loading)

Post 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..
JohnnyTheDon
Member
Member
Posts: 524
Joined: Sun Nov 09, 2008 2:55 am
Location: Pennsylvania, USA

Re: Realocate code during execution (chain loading)

Post 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 :)
mangaluve
Member
Member
Posts: 110
Joined: Mon Feb 23, 2009 6:53 am

Re: Realocate code during execution (chain loading)

Post 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?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Realocate code during execution (chain loading)

Post by Combuster »

No, addressing is different in Real Mode
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Re: Realocate code during execution (chain loading)

Post 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
JohnnyTheDon
Member
Member
Posts: 524
Joined: Sun Nov 09, 2008 2:55 am
Location: Pennsylvania, USA

Re: Realocate code during execution (chain loading)

Post 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.
Post Reply