[solved] Real Mode Confusion

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
theseankelly
Posts: 20
Joined: Sat Oct 22, 2011 4:17 pm

Re: Real Mode Confusion

Post by theseankelly »

Well he removed ret, and now I know more about the int command :)

Thanks
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: Real Mode Confusion

Post by Combuster »

Code: Select all

   int 0x10
[section .bss]
stack:
   resb 0x600
You know what happens after the int 0x10 now?
"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 ]
RobertF
Member
Member
Posts: 25
Joined: Tue Oct 18, 2011 12:55 am

Re: Real Mode Confusion

Post by RobertF »

Combuster wrote:You know what happens after the int 0x10 now?
I'm assuming the next thing to execute would be a bunch of uninitialized data? Although I feel like I'm wrong because I get the same result regardless of whether I do nothing after the int 0x10 or just loop.
User avatar
Chandra
Member
Member
Posts: 487
Joined: Sat Jul 17, 2010 12:45 am

Re: Real Mode Confusion

Post by Chandra »

RobertF wrote:I'm assuming the next thing to execute would be a bunch of uninitialized data? Although I feel like I'm wrong because I get the same result regardless of whether I do nothing after the int 0x10 or just loop.
Check the Bochs debug window to make sure you've actually entered Real Mode. Examine the size of segment registers. Once that is done, fix the stack, again.(Hint: Your approach is right but not the implementation)
Programming is not about using a language to solve a problem, it's about using logic to find a solution !
RobertF
Member
Member
Posts: 25
Joined: Tue Oct 18, 2011 12:55 am

Re: Real Mode Confusion

Post by RobertF »

Chandra wrote:Check the Bochs debug window to make sure you've actually entered Real Mode. Examine the size of segment registers. Once that is done, fix the stack, again.(Hint: Your approach is right but not the implementation)
I'm completely baffled. Using the same code from before, which didn't cause any errors (although still didn't call the BIOS), I'm now getting one "SLDT: not recognized in real or v8086 mode" and a bunch of "LOCK prefix unallowed."

Code: Select all

00436860000i[CPU0 ] CPU is in real mode (active)
00436860000i[CPU0 ] CS.d_b = 16 bit
00436860000i[CPU0 ] SS.d_b = 16 bit
00436860000i[CPU0 ] | EAX=001bfb01  EBX=00000541  ECX=001b0a85  EDX=001ba9ea
00436860000i[CPU0 ] | ESP=00115c9b  EBP=00117fe9  ESI=0002c63a  EDI=0002c6db
00436860000i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt OF df if tf sf ZF AF PF CF
00436860000i[CPU0 ] | SEG selector     base    limit G D
00436860000i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00436860000i[CPU0 ] |  CS:0000( 0003| 0|  0) 00000000 000fffff 0 0
00436860000i[CPU0 ] |  DS:c63a( 0004| 0|  0) 000c63a0 000fffff 0 0
00436860000i[CPU0 ] |  SS:ffff( 0004| 0|  0) 000ffff0 000fffff 0 0
00436860000i[CPU0 ] |  ES:0000( 0004| 0|  0) 00000000 000fffff 0 0
00436860000i[CPU0 ] |  FS:0000( 0004| 0|  0) 00000000 000fffff 0 0
00436860000i[CPU0 ] |  GS:0000( 0004| 0|  0) 00000000 000fffff 0 0
00436860000i[CPU0 ] | EIP=00000407 (00000407)
00436860000i[CPU0 ] | CR0=0x60000010 CR2=0x00000000
00436860000i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00436860000i[CPU0 ] 0x00000407>> add byte ptr ds:[bx+si], al : 0000


So I am in real mode, at least. I thought the fact that CS and SS being 16-bit was a hint, but I don't see how. Before, when I didn't get the errors I am now, the ss selector stayed at 0. I notice now it's at its limit. Is this why I'm getting the "LOCK prefix unallowed" errors?

Is there anything I could read that would give a little insight on how I should properly set up the stack? I've read the segmentation page on the wiki as turdus suggested, but from what I gathered, I thought I would be able to make the stack pointer anywhere inside the 16KB window and it would work fine.
User avatar
Chandra
Member
Member
Posts: 487
Joined: Sat Jul 17, 2010 12:45 am

Re: Real Mode Confusion

Post by Chandra »

Is there anything I could read that would give a little insight on how I should properly set up the stack? I've read the segmentation page on the wiki as turdus suggested, but from what I gathered, I thought I would be able to make the stack pointer anywhere inside the 16KB window and it would work fine.
Take this:

Code: Select all

resb 0x400 ; Reserve 1 kb space   
stack:

Code: Select all

00436860000i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00436860000i[CPU0 ] |  CS:0000( 0003| 0|  0) 00000000 000fffff 0 0
00436860000i[CPU0 ] |  DS:c63a( 0004| 0|  0) 000c63a0 000fffff 0 0
00436860000i[CPU0 ] |  SS:ffff( 0004| 0|  0) 000ffff0 000fffff 0 0
00436860000i[CPU0 ] |  ES:0000( 0004| 0|  0) 00000000 000fffff 0 0
00436860000i[CPU0 ] |  FS:0000( 0004| 0|  0) 00000000 000fffff 0 0
00436860000i[CPU0 ] |  GS:0000( 0004| 0|  0) 00000000 000fffff 0 0
That gives me the feeling that you've loaded invalid selectors. Are you sure 0x18 and 0x20 corresponds to the proper real mode code and data selectors? You should double check the GDT structure for these selectors and if no progress, post that code too.
Programming is not about using a language to solve a problem, it's about using logic to find a solution !
RobertF
Member
Member
Posts: 25
Joined: Tue Oct 18, 2011 12:55 am

Re: Real Mode Confusion

Post by RobertF »

Chandra wrote:That gives me the feeling that you've loaded invalid selectors. Are you sure 0x18 and 0x20 corresponds to the proper real mode code and data selectors? You should double check the GDT structure for these selectors and if no progress, post that code too.
It should:

Code: Select all

  
    gdt_set_gate(0, 0, 0, 0, 0);          
    gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
    gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
    gdt_set_gate(3, 0, 0xFFFFF, 0x9A, 0);   
    gdt_set_gate(4, 0, 0xFFFFF, 0x92, 0);  
Edit: It appears selectors will change based on when I load the real mode IDT
User avatar
Chandra
Member
Member
Posts: 487
Joined: Sat Jul 17, 2010 12:45 am

Re: Real Mode Confusion

Post by Chandra »

RobertF wrote:

Code: Select all

 
gdt_set_gate(0, 0, 0, 0, 0); 
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
gdt_set_gate(3, 0, 0xFFFFF, 0x9A, 0); 
gdt_set_gate(4, 0, 0xFFFFF, 0x92, 0); 
That looks fine.
I'm now getting one "SLDT: not recognized in real or v8086 mode"
That's weird. I don't suppose you've executed any such instruction from your code. Now the only way from here is to attach full source code(try to keep it minimal as possible, including only stuffs that are related).

Code: Select all

00436860000i[CPU0 ] | ESP=00115c9b  EBP=00117fe9 
Fix the stack.

Code: Select all

00436860000i[CPU0 ] | EIP=00000407 (00000407)
Quite possible that one of the far jmp is broken.
Edit: It appears selectors will change based on when I load the real mode IDT
Or, probably the Real mode IVT is overwritten.
Programming is not about using a language to solve a problem, it's about using logic to find a solution !
mitikoro
Posts: 11
Joined: Tue Sep 01, 2009 10:19 am

Re: Real Mode Confusion

Post by mitikoro »

you have code to return to PM, do you? does the code actually change video mode?
RobertF
Member
Member
Posts: 25
Joined: Tue Oct 18, 2011 12:55 am

Re: Real Mode Confusion

Post by RobertF »

mitikoro wrote:you have code to return to PM, do you? does the code actually change video mode?
Not yet; I'm still working on getting it to change video mode.

Speaking of, I played around a bit and noticed I was overwriting the IVT (stupidly). Although I fixed that issue, it still wouldn't work so I copied the IVT to 0x4000, and now after tweaking the code more, I got to somewhere that looks close to what I need.

Code: Select all

00351898970e[CPU0 ] interrupt(real mode) vector > idtr.limit
00351898970e[CPU0 ] interrupt(real mode) vector > idtr.limit
00351898970e[CPU0 ] interrupt(real mode) vector > idtr.limit
00351898970i[CPU0 ] CPU is in real mode (active)
00351898970i[CPU0 ] CS.d_b = 16 bit
00351898970i[CPU0 ] SS.d_b = 16 bit
00351898970i[CPU0 ] | EAX=60000003  EBX=0002c560  ECX=00000001  EDX=000003d5
00351898970i[CPU0 ] | ESP=00008264  EBP=00117fe8  ESI=0002c6da  EDI=0002c6db
00351898970i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df IF tf sf zf af pf cf
00351898970i[CPU0 ] | SEG selector     base    limit G D
00351898970i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00351898970i[CPU0 ] |  CS:0000( 0003| 0|  0) 00000000 000fffff 0 0
00351898970i[CPU0 ] |  DS:4000( 0004| 0|  0) 00040000 000fffff 0 0
00351898970i[CPU0 ] |  SS:4000( 0004| 0|  0) 00040000 000fffff 0 0
00351898970i[CPU0 ] |  ES:4000( 0004| 0|  0) 00040000 000fffff 0 0
00351898970i[CPU0 ] |  FS:4000( 0004| 0|  0) 00040000 000fffff 0 0
00351898970i[CPU0 ] |  GS:4000( 0004| 0|  0) 00040000 000fffff 0 0
00351898970i[CPU0 ] | EIP=00007e5c (00007e5c)
00351898970i[CPU0 ] | CR0=0x60000010 CR2=0x00000000
00351898970i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00351898970i[CPU0 ] 0x00007e5c>> int 0x10 : CD10
00351898970e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
Although that exception is obviously not a good thing. I'm getting "interrupt(real mode) vector ..." error because I'm loading the IDT after I set the real mode segments. I probably shouldn't do that, but as I said, what I have right now seems close. (I tried changing the limit of the IDT but that didn't seem to fix it)
mitikoro
Posts: 11
Joined: Tue Sep 01, 2009 10:19 am

Re: Real Mode Confusion

Post by mitikoro »

the data segment registers are set to 0x4000, why?
RobertF
Member
Member
Posts: 25
Joined: Tue Oct 18, 2011 12:55 am

Re: Real Mode Confusion

Post by RobertF »

mitikoro wrote:the data segment registers are set to 0x4000, why?
I thought copying the first 0x400 bytes to 0x4000 and setting the segment registers to 0x4000 would make a difference—apparently I'm wrong because I can set the segment registers to anything and get the same error I've been getting. Back to square one, I guess.
mitikoro
Posts: 11
Joined: Tue Sep 01, 2009 10:19 am

Re: Real Mode Confusion

Post by mitikoro »

In real mode, if you set a segment register to 0x4000, any access using that register will end up at 0x4000*16 + offset.
So if you copy the IDT (using movs) with ES set to 0x4000, you'll end up copying it at 0x40000, not 0x4000.
Anyway, I don't think relocating the IDT is a good idea. Would you mind posting the new code?
RobertF
Member
Member
Posts: 25
Joined: Tue Oct 18, 2011 12:55 am

Re: Real Mode Confusion

Post by RobertF »

Code: Select all

[bits 32]
[org 0x7E00]

PMode32:
	cli          	        	; disable interrupts 
   
	mov eax, cr0
	and eax, 0x7FFFFFFF      	; clear pg bit 
	mov cr0, eax 
   
	xor eax, eax
	mov cr3, eax    		    ; flush TLB 
   
	jmp 0x18:PMode16     		; far jump to 16-bit protected mode 
[bits 16]
RealIDT:
	dw 0x3FF 
	dd 0x0
PMode16:
	mov ax, 0x20          		; load 16-bit gdt data segment 
	mov ds, ax 
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov ss, ax

	mov eax, cr0
	and eax, 0xFFFFFFFE      	; clear pe bit 
	mov cr0, eax 

	jmp 0:RMode            		; far jump to real mode 
RMode:
	mov esp, stack				; should I be using sp instead?
    
	mov ax, 0x0
	mov ds, ax
	mov es, ax
	mov fs, ax 
	mov gs, ax
	mov ss, ax
   	
	lidt [RealIDT]

	sti

	mov ah,0x0
	mov al,0x13
	int 0x10

	.loop: jmp .loop			; loop for now
[section .bss]
	resb 0x400 ; Reserve 1 kb space   
stack:
mitikoro
Posts: 11
Joined: Tue Sep 01, 2009 10:19 am

Re: Real Mode Confusion

Post by mitikoro »

Try moving the lidt instruction to 32-bit PM, just after the cli opcode. Also, dump the value of the IDTR before the BIOS call
(using bochs debugger, command sregs)
Post Reply