@iansjack:
It is because of single-stepping that I know that it is copying to both EDI and DI. I ran the following on bochs before and after several iterations.
Code: Select all
x /1dx 0x3000
x /1dx 0x0000
x /1dx 0x100000
BOTH 0x0000 and 0x100000 are being changed.
Also, when comparing with the image on the virtual floppy drive I have open in a HEX editor, I know that the kernel is definitely loaded correctly at 0x3000 and then being copied.
I originally wanted to include all the state data along with my original post but it seemed onerous given that I can't copy-paste from the debug window of Bochs, meaning that I have to type it all by hand. I include it now:
BEFORE copying kernel to 1MB:
Code: Select all
rax: 00000000_00000400 rcx: 00000000_00000400
rdx: 00000000_00000000 rbx: 00000000_00000004
rsp: 00000000_00090000 rbp: 00000000_00003000
rsi: 00000000_00003000 rdi: 00000000_00100000
r8 : 00000000_00000000 r9 : 00000000_00000000
r10: 00000000_00000000 r11: 00000000_00000000
r12: 00000000_00000000 r13: 00000000_00000000
r14: 00000000_00000000 r15: 00000000_00000000
rip: 00000000_0000098a
eflags 0x00000046: id vip vif ac vm rf nt IOPL=0 of df if tf sf ZF af PF cf
es:0x0010, dh=0x00cf9300, dl=0x0000ffff, valid=31
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
cs:0x0008, dh=0x00cf9b00, dl=0x0000ffff, valid=1
Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-conforming, Accessed, 32-bit
ss:0x0010, dh=0x00cf9300, dl=0x0000ffff, valid=31
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
ds:0x0010, dh=0x00cf9300, dl=0x0000ffff, valid=31
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
fs:0x0010, dh=0x00cf9300, dl=0x0000ffff, valid=31
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
gs:0x0010, dh=0x00cf9300, dl=0x0000ffff, valid=31
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
ldtr:0x0000, dh=0x00008200, dl=0x0000ffff, valid=1
tr:0x0000, dh=0x00008b00, dl=0x0000ffff, valid=1
gdtr:base=0x000000000000060e, limit=0x17
idtr:base=0x0000000000000000, limit=0x3ff
AFTER copying the kernel to 1MB:
Code: Select all
rax: 00000000_00000400 rcx: 00000000_0000019d
rdx: 00000000_00000000 rbx: 00000000_00000004
rsp: 00000000_00090000 rbp: 00000000_00003000
rsi: 00000000_0000398c rdi: 00000000_0010098c
r8 : 00000000_00000000 r9 : 00000000_00000000
r10: 00000000_00000000 r11: 00000000_00000000
r12: 00000000_00000000 r13: 00000000_00000000
r14: 00000000_00000000 r15: 00000000_00000000
rip: 00000000_0000098c
eflags 0x00000006: id vip vif ac vm rf nt IOPL=0 of df if tf sf zf af PF cf
es:0x0010, dh=0x00cf9300, dl=0x0000ffff, valid=31
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
cs:0x0008, dh=0x00cf9b00, dl=0x0000ffff, valid=1
Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-conforming, Accessed, 32-bit
ss:0x0010, dh=0x00cf9300, dl=0x0000ffff, valid=31
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
ds:0x0010, dh=0x00cf9300, dl=0x0000ffff, valid=31
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
fs:0x0010, dh=0x00cf9300, dl=0x0000ffff, valid=31
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
gs:0x0010, dh=0x00cf9300, dl=0x0000ffff, valid=31
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
ldtr:0x0000, dh=0x00008200, dl=0x0000ffff, valid=1
tr:0x0000, dh=0x00008b00, dl=0x0000ffff, valid=1
gdtr:base=0x000000000000060e, limit=0x17
idtr:base=0x0000000000000000, limit=0x3ff
As @neon stated: ImageSize is exactly as in the tutorial, it holds the number of sectors that were loaded to 0x3000. The calculation before the CLD statement determines the number of iterations.
@combuster:
I'm definitely in 32-bit mode at the point the code snippet executes, further up the execution are the following two sections:
Code: Select all
;------------------------------------------;
; Install the GDT ;
;------------------------------------------;
call InstallGDT
;------------------------------------------;
; Enable Gate A20 ;
;------------------------------------------;
call EnableA20_KKbrd
Code: Select all
;------------------------------------------;
; Go into protected mode ;
;------------------------------------------;
EnterStage3:
cli ; turn off all interrupts
mov eax, cr0 ; set bit 0 in cr0 --> enter pmode
or eax, 1
mov cr0, eax
jmp 08h:Stage3 ; far jump to fix CS. Remember that the code selector is 0x8
; Note: Do NOT re-enable the interrupts once in pmode. This will cause a triple-fault!
The memory address of the REP MOVSD command is reported by bochs as: 0008:000000000000098a
I read about the "a32" on another website and tried it but, alas, without any difference. Data is still being copied to both EDI and DI
@neon:
I've never had to program on such a low level before so I went through all the steps mentioned on the
MSVS page very slowly, many of the settings I don't really understand fully. I have double-checked that my linker indeed has /ALIGN:512. It might be worthy of noting though that I'm using MSVS-2015 but since the problem is in stage2, I don't know if this is significant yet.
The kernel is completely identical to that of Demo6_1 and compiles to 4096 bytes.
@alexfru:
EDX is definitely 0x0 before the DIV, in fact the entire RDX is 0x0. I learnt that lesson a few chapters back.