How is MOVSD supposed to work?
Posted: Wed Jun 08, 2016 2:30 pm
I have been following the Brokenthorn OS Developement Series but have hit a snag in Chapter 14
Initially, when I ran the code, I kept on getting triple-fault errors after jumping to the kernel code but after a lot of tracing and stepping through code line-by-line, I found the root cause of my problem: the line where stage 2 copies the loaded kernel to the 1MB mark.
(snippet from: Demo6\SysBoot\Stage2\stage2.asm)
The line causing the problem is the last one: "rep movsd"
My problem is as follows:
1. The kernel is successfully loaded from the floppy image to the 0x3000 mark.
2. Gate A20 is enabled, the GDT is set up and then we switch to Protected Mode.
3. Now that there's access to up to 4GB of memory, we create a copy of the kernel at the 1MB mark, then jump to the kernel at 0x100000
4. The first thing the kernel must do is set up the segment registers but this is the point where the entire system crashes.
When execution reached the point where the kernel is copied, the GDT was as follows:
The questions are thus:
1. If MOVSD is supposed to copy data from [DS:ESI] to [ES:EDI], why is it simultaneously copying from [DS:SI] to [ES:DI] as well? (I have gone through the code multiple times and definitely both destinations are being copied to.)
2. How do I copy the kernel to the 1MB mark without overwriting my GDT?
* I am using Bochs 2.6.8 as my emulator
Initially, when I ran the code, I kept on getting triple-fault errors after jumping to the kernel code but after a lot of tracing and stepping through code line-by-line, I found the root cause of my problem: the line where stage 2 copies the loaded kernel to the 1MB mark.
(snippet from: Demo6\SysBoot\Stage2\stage2.asm)
Code: Select all
CopyImage:
mov eax, dword [ImageSize]
movzx ebx, word [bpbBytesPerSector]
mul ebx
mov ebx, 4
div ebx
cld
mov esi, IMAGE_RMODE_BASE
mov edi, IMAGE_PMODE_BASE
mov ecx, eax
rep movsd ; copy image to its protected mode address
My problem is as follows:
1. The kernel is successfully loaded from the floppy image to the 0x3000 mark.
2. Gate A20 is enabled, the GDT is set up and then we switch to Protected Mode.
3. Now that there's access to up to 4GB of memory, we create a copy of the kernel at the 1MB mark, then jump to the kernel at 0x100000
4. The first thing the kernel must do is set up the segment registers but this is the point where the entire system crashes.
When execution reached the point where the kernel is copied, the GDT was as follows:
After allowing the "rep movsd" to complete, the GDT was as follows:<bochs:27>info gdt 0 4
Global Descriptor Table (base=0x000000000000060e, limit=23)
GDT[0x00]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x01]=Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-conforming, Accessed, 32-bit
GDT[0x02]=Data segment base=0x00000000, limit=0xffffffff, Read/Write, Accessed
By stepping through the code and examining the various memory locations, it turns out that the kernel is definitely being copied from 0x3000 to 0x100000, but, it turns out that the data is also being copied over the bootloader as well, and since the GDT is located at 0x60e, it is getting overwritten.Global Descriptor Table (base=0x000000000000060e, limit=23)
GDT[0x00]=??? descriptor hi=0x418b0000, lo=0x008be900
GDT[0x01]=16-Bit TSS (Busy) at 0x0414247c, length 0x18d04
GDT[0x02]=32-Bit TSS (Available) at 0x24001424, length 0xc44c6
The questions are thus:
1. If MOVSD is supposed to copy data from [DS:ESI] to [ES:EDI], why is it simultaneously copying from [DS:SI] to [ES:DI] as well? (I have gone through the code multiple times and definitely both destinations are being copied to.)
2. How do I copy the kernel to the 1MB mark without overwriting my GDT?
* I am using Bochs 2.6.8 as my emulator