[SOLVED]Entering protected mode: tutorial disambiguation

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.
M2004
Member
Member
Posts: 65
Joined: Sun Mar 07, 2010 2:12 am

Re: Entering protected mode: tutorial disambiguation

Post by M2004 »

guilherme wrote:BOOTSECTOR:
Code:
[BITS 16]
[Org 0x7C00]
CLI
Xor ax,ax
Push ax
Popf
Mov es,ax
Mov ds,ax
Mov ss,ax
Mov bp,07E00h
Mov sp,07FFEh
Your are using stack before setting it up properly.

regards
Mac2004
guilherme
Member
Member
Posts: 35
Joined: Mon Jan 31, 2011 6:58 am
Location: Brasil

Re: Entering protected mode: tutorial disambiguation

Post by guilherme »

Ok, now my problem is different.
Sorry by don't explaining this better, but now is 4:00h am here i'm Brasil and i'm fighting against the sleepiness, and my computer will crash in some minutes (it is overclocked, and the mean time for error has been reduced to 5~6 hours).
This code i made now is a real-mode kernel, that copies data from disk to a base memory area, calls a routine that enter protected mode, copy this data to an extended memory area and return to real-mode, and later this buffered data will be write on another disk area, and there's a routine that show a counting on screen, so i can now how is the going the copy.
The problem is: The code reboots in a random time after starting, what means that the problem is not related to a stack overflow or a triple fault, and once i don't use hardware interrupts, i don't know what this can be.

There's the code (WRITEEXT, READEXT, RESETEXT and ENCODE are those routines that enter and exit protected mode, and should return
to the real-mode code that called it Leaving all registers and flags intact).

ATTENTION!!! : This code must be run in a emulator that support disk emulation, and, if you going to test it in a real computer with a real hard disk, use a empity hard disk, because this code will destroy any data on it!!!.


Code: Select all

[BITS 16]            
[ORG 0x0500]
CLI
Xor ax,ax
Push ax
Popf        
Mov ds,ax
Mov ss,ax 
Mov ax,0B800h
Mov es,ax 
Mov bp,STACK
Mov sp,STACK+0200h
Mov ah,01h
Mov cx,02B0Bh
Int 010h  
Xor ax,ax  
Xor di,di
Mov cx,03Eh 
LOOPCLEAR: 
Stosw  
Stosw  
Stosw  
Stosw  
Stosw  
Stosw  
Stosw  
Stosw
Stosw  
Stosw  
Stosw  
Stosw
Stosw  
Stosw  
Stosw  
Stosw  
Stosw  
Stosw  
Stosw  
Stosw  
Stosw  
Stosw  
Stosw  
Stosw
Stosw  
Stosw  
Stosw  
Stosw
Stosw  
Stosw  
Stosw  
Stosw
Loop LOOPCLEAR
Stosw  
Stosw  
Stosw  
Stosw 
Stosw  
Stosw  
Stosw  
Stosw  
Stosw  
Stosw  
Stosw  
Stosw 
Stosw  
Stosw  
Stosw  
Stosw 
RESET:
Xor ax,ax
Mov dx,080h
Int 013h
Jnc START
Pusha
Mov ax,0E07h     
Int 010h 
Mov ax,0E07h     
Int 010h  
Mov ax,0E07h     
Int 010h 
Mov ax,0E07h     
Int 010h 
Mov ax,0E07h     
Int 010h  
Mov ax,0E07h     
Int 010h
Popa
Jmp RESET
START:
Mov word  [es:00h],00F5Bh     
Mov word  [es:014h],00F5Dh 
Mov word  [es:016h],00F4Dh
Mov word  [es:018h],00F62h    
Mov dx,080h      
READISK:  
Call RESETEXT 
Mov cx,03Fh  
Mov byte  [COUNTER],0FAh
Mov si,DRD
READLOOP:
Mov ax,04200h
Int 013h  
Jc DORESET 
Loop CDRD
Call WRITEEXT
Mov word  [OFFBUFF1],00000h
Mov word  [SEGBUFF1],01000h 
Mov cx,03Fh
Call SHOWSTAT 
Sub byte  [COUNTER],01h 
Jnz READLOOP
Jmp DISCHARGE
DORESET:
Cmp di,05h
Jz CDRD      
Pusha    
Mov ax,0E07h     
Int 010h 
Mov ax,0E07h     
Int 010h  
Mov ax,0E07h     
Int 010h 
Xor ax,ax
Int 013h
Popa       
Inc di
Jmp READLOOP
CDRD:
Xor di,di       
Add word  [OFFBUFF1],02000h 
Jnc CONTDRD
Add word  [SEGBUFF1],01000h
CONTDRD: 
Add word  [SECTOR11],010h
Jnc READLOOP
Inc word  [SECTOR21]
Jmp READLOOP



DISCHARGE: 
Call RESETEXT
Call ENCODE  
Mov byte  [COUNTER],0FAh
Mov si,DWD
WRITELOOP:  
Call READEXT
Mov word  [OFFBUFF2],00000h
Mov word  [SEGBUFF2],01000h 
Mov cx,03Fh
Call SHOWSTAT 
INLOOP:     
Mov ax,04300h
Int 013h  
Jc DOSET 
Loop CDWD
Sub byte  [COUNTER],01h 
Jnz WRITELOOP 
Sub byte  [MAINCOUNTER],01h
Jnz READISK
HLT
Jmp $ 
DOSET:
Cmp di,05h
Jz CDWD     
Pusha    
Mov ax,0E07h     
Int 010h 
Mov ax,0E07h     
Int 010h  
Mov ax,0E07h     
Int 010h 
Xor ax,ax
Int 013h
Popa       
Inc di
Jmp INLOOP
CDWD:
Xor di,di       
Add word  [OFFBUFF2],02000h 
Jnc CONTDWD
Add word  [SEGBUFF2],01000h
CONTDWD: 
Add word  [SECTOR12],010h
Jnc INLOOP
Inc word  [SECTOR22]
Jmp INLOOP   

WRITEEXT:
Pushfd
Pushad
Push ds
Push  es
Xor eax,eax 
Mov ds,eax
Mov es,eax
lgdt [GDTP]          
Mov eax,CR0           
Or eax,01h      
Mov CR0,eax    
Jmp 08h:CLEARA
[BITS 32]           
CLEARA:           
Mov eax,010h       
Mov ds,eax
Mov es,eax
Mov esi,010000h
Mov edi,[LASTDESTIN]
Mov ecx,01F800h
Rep Movsd
Mov [LASTDESTIN],edi
Jmp 018h:REALA
[BITS 16]      
REALA: 
Mov eax,020h
Mov ds,eax
Mov es,eax
Mov eax,CR0           
Xor eax,01h      
Mov CR0,eax    
Jmp 0000h:REALB
REALB:
Pop es
Pop ds
Popad
Popfd
Ret




READEXT:
Pushfd
Pushad
Push ds
Push  es
Xor eax,eax 
Mov ds,eax
Mov es,eax
lgdt [GDTP]          
Mov eax,CR0           
Or eax,01h      
Mov CR0,eax    
Jmp 08h:CLEARB
[BITS 32]           
CLEARB:           
Mov eax,010h       
Mov ds,eax
Mov es,eax
Mov edi,010000h
Mov esi,[LASTSOURCE]
Mov ecx,01F800h
Rep Movsd
Mov [LASTSOURCE],esi
Jmp 018h:REALC
[BITS 16]      
REALC: 
Mov eax,020h
Mov ds,eax
Mov es,eax
Mov eax,CR0           
Xor eax,01h      
Mov CR0,eax    
Jmp 0000h:REALD
REALD:
Pop es
Pop ds
Popad
Popfd
Ret





ENCODE:
Pushfd
Pushad
Push ds
Push  es
Xor eax,eax 
Mov ds,eax
Mov es,eax
lgdt [GDTP]          
Mov eax,CR0           
Or eax,01h      
Mov CR0,eax    
Jmp 08h:CLEARC
[BITS 32]           
CLEARC:           
Mov eax,010h       
Mov ds,eax
Mov es,eax
Mov ebx,0200000h
LOOPENCODE:
Mov eax,[ebx+04h]
Add [ebx],eax
Add ebx,04h
Cmp ebx,07D0C000h
Jb LOOPENCODE
Jmp 018h:REALE
[BITS 16]      
REALE: 
Mov eax,020h
Mov ds,eax
Mov es,eax
Mov eax,CR0           
Xor eax,01h      
Mov CR0,eax    
Jmp 0000h:REALF
REALF:
Pop es
Pop ds
Popad
Popfd
Ret




RESETEXT:
Pushfd
Pushad
Push ds
Push  es
Xor eax,eax 
Mov ds,eax
Mov es,eax
lgdt [GDTP]          
Mov eax,CR0           
Or eax,01h      
Mov CR0,eax    
Jmp 08h:CLEARD
[BITS 32]           
CLEARD:           
Mov eax,010h       
Mov ds,eax
Mov es,eax
Mov eax,0200000h
Mov [LASTDESTIN],eax
Mov [LASTSOURCE],eax
Jmp 018h:REALG
[BITS 16]      
REALG: 
Mov eax,020h
Mov ds,eax
Mov es,eax
Mov eax,CR0           
Xor eax,01h      
Mov CR0,eax    
Jmp 0000h:REALH
REALH:
Pop es
Pop ds
Popad
Popfd
Ret






SHOWSTAT:  
Pusha             
Mov di,0Ah
Inc word  [MBCOUNTER1]
Cmp word  [MBCOUNTER1],02710h
Jne CONTN
Xor word  [MBCOUNTER1],02710h
Inc word  [MBCOUNTER2]
CONTN:  
Mov ax,[MBCOUNTER1]
Mov bx,02710h
Xor dx,dx
Div bx
Add ax,0F30h
Stosw
Mov ax,dx
Mov bx,03E8h
Xor dx,dx
Div bx
Add ax,0F30h
Stosw
Mov ax,dx 
Mov bx,064h
Xor dx,dx
Div bx
Add ax,0F30h
Stosw
Mov ax,dx 
Mov bx,0Ah
Xor dx,dx
Div bx
Add ax,0F30h
Stosw
Add dx,0F30h
Mov [es:di],dx
Mov di,02h
Mov ax,[MBCOUNTER2]
Mov bx,02710h
Xor dx,dx
Div bx
Add ax,0F30h
Stosw
Mov ax,dx
Mov bx,03E8h
Xor dx,dx
Div bx
Add ax,0F30h
Stosw
Mov ax,dx 
Mov bx,064h
Xor dx,dx
Div bx
Add ax,0F30h
Stosw
Mov ax,dx 
Mov bx,0Ah
Xor dx,dx
Div bx
Add ax,0F30h
Stosw
Add dx,0F30h
Mov [es:di],dx
Popa
Ret     

DRD: 
dd 00100010h
OFFBUFF1 dw 00000h
SEGBUFF1 dw 01000h
SECTOR11 dw 0000h
SECTOR21 dw 0000h     
dd 00000000h

DWD:
dd 00100010h
OFFBUFF2 dw 00000h
SEGBUFF2 dw 01000h
SECTOR12 dw 04E4Ch
SECTOR22 dw 063Eh    
dd 00000000h


MAINCOUNTER db 0A6h  
MBCOUNTER1 dw 0000h
MBCOUNTER2 dw 0000h  
COUNTER db 0FAh

LASTDESTIN dd 00200000h
LASTSOURCE dd 00200000h

GDT:  
dq 00000000000000000h  

dw 0FFFFh  
dw 00000h
db 00h   
db 010011010b 
db 011001111b
db 00h   

dw 0FFFFh  
dw 00000h
db 00h   
db 010010010b 
db 011001111b
db 00h  

dw 0FFFFh  
dw 00000h
db 00h   
db 010011010b 
db 010001111b
db 00h   

dw 0FFFFh  
dw 00000h
db 00h   
db 010010010b 
db 010001111b
db 00h  

GDTP:                           
dw GDTP-GDT-1        
dd GDT     

STACK:
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
dd 00000000h
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Entering protected mode: tutorial disambiguation

Post by Solar »

guilherme wrote:

Code: Select all

STACK:
dd 00000000h
<repeated X times>
WTF?

Dude, are you really sure your ASM skills are up to par with kernel-space development work?

I mean:
  • no indentation (as neon said before),
  • no comments whatsoever (as neon said before),
  • code so poor that even I - a complete ASM noob - know there are better ways to do it than spamming hundreds of zeroes to the forum.
:?

PS: Seriously. It took me a minute to look it up:

Code: Select all

TIMES <insert_number_here> dd 0
Every good solution is obvious once you've found it.
guilherme
Member
Member
Posts: 35
Joined: Mon Jan 31, 2011 6:58 am
Location: Brasil

Re: Entering protected mode: tutorial disambiguation

Post by guilherme »

Firstly i'm not a ASM noob, i may be a begginer in the NASM compiler, but i have years of experiece on other compilers.
I changed of compiler because the compiler that i used before didn't supports 32-bit protected mode programming, and as i said, i did that at four hours and a half of the morning, so i was very much tired, and i didn't have time to search how to do this in the right way, so i copied the DD's 256 times to do a 1024 bytes stack, and about that lots of Stosw's and Lodsb's, i did this because the compiler in wich originally i did that code have an very slow emulator, and once the Rep instruction occupies some time, i removed it, to run more fastly.
guilherme
Member
Member
Posts: 35
Joined: Mon Jan 31, 2011 6:58 am
Location: Brasil

Re: Entering protected mode: tutorial disambiguation

Post by guilherme »

Be patient, now i sleeped, and i'll put some comments on the code.
User avatar
Chandra
Member
Member
Posts: 487
Joined: Sat Jul 17, 2010 12:45 am

Re: Entering protected mode: tutorial disambiguation

Post by Chandra »

We don't have a wiki article regarding switching to real mode from protected mode,right?

Okay I'll try to write it in such a fashion that it'll be useful for people having trouble in similar topic.

First off, a little introduction:
Intel's Manual wrote:
The processor reenters real-address mode if software clears the PE bit in
CR0 with a MOV to CR0 instruction. A procedure that attempts to do this,
however, should proceed as follows:

1. If paging is enabled, perform the following sequence:

þ Transfer control to linear addresses that have an identity mapping;
i.e., linear addresses equal physical addresses.

þ Clear the PG bit in CR0.

þ Move zeros to CR3 to clear out the paging cache.

2. Transfer control to a segment that has a limit of 64K (FFFFH). This
loads the CS register with the limit it needs to have in real mode.

3. Load segment registers SS, DS, ES, FS, and GS with a selector that
points to a descriptor containing the following values, which are
appropriate to real mode:

þ Limit = 64K (FFFFH)
þ Byte granular (G = 0)
þ Expand up (E = 0)
þ Writable (W = 1)
þ Present (P = 1)
þ Base = any value

4. Disable interrupts. A CLI instruction disables INTR interrupts. NMIs
can be disabled with external circuitry.

5. Clear the PE bit.

6. Jump to the real mode code to be executed using a far JMP. This
action flushes the instruction queue and puts appropriate values in
the access rights of the CS register.

7. Use the LIDT instruction to load the base and limit of the real-mode
interrupt vector table.

8. Enable interrupts.

9. Load the segment registers as needed by the real-mode code.
.

Based on this, here's a little trick to switch to real mode from protected mode.

Code: Select all

;; Assume your protected mode code being here
;; If your are using paging disable it.

   cli            		; We'll now enter real mode from protected mode (disable interrupts)
   
   lgdt [realmode_gdt_info]                  ; Our GDT for real mode
      
   jmp 08h:test_function   	; Far Jump to real mode code segement(selector=08h), offset test_function

[BITS 16]

test_function:
   
   mov bx,10h         		; Initalize the segment registers with real mode data segment(selector=10h)
   mov ds,bx
   mov ss,bx
   mov es,bx
   mov fs,bx
   mov gs,bx
      
   mov eax,cr0                ; Clear the PE bit
   and al,0xFE
   mov cr0,eax
      
   jmp 0x0000:real_mode_code  ; Far Jump to real mode code to be executed (segment:offset)



real_mode_code:
   lidt [realmode_idt]         		; Restore the Real mode IVT
   mov ax,0x0         		; Initalize the segment registers to where we are loaded
   mov ds,ax
   mov es,ax
   mov fs,ax
   mov ss,ax
   mov gs,ax
   sti   

   mov ah,0x00         		; Initialize 80x25 Text mode (Clears the screen)
   mov al,0x02         		; You may replace this with your own real mode stuff
   int 0x10

   cli				; Just to end this stuff here                                                  
   hlt

realmode_gdt:   

gdt_realmode_null:            ; Null Segment
        dd 0
        dd 0


gdt_realmode_code:
        dw 0ffffh         	; Limit 64 KB
        dw 0      		; Base 0
        db 0
        db 10011010b
        db 00001111b      	; Granularity 0
        db 0

gdt_realmode_data:
        dw 0ffffh         	; Limit 64 KB
        dw 0      		; Base 0
        db 0
        db 10010010b
        db 00001111b      	; Granularity 0
        db 0

realmode_gdt_end:

realmode_gdt_info:
   dw realmode_gdt_end - realmode_gdt -1
   dd realmode_gdt

realmode_idt:
   dw 03ffh      	; Limit of IDT (real mode IVT)
   dd 0      	; Address of IDT (real mode IVT)
You can simply add your real mode code segment and data segment entry to your original protected mode GDT entry,instead of initializing a new GDT. But to avoid confusion, I initalized a new GDT for use with real mode.

Hope this helps someone.

Best Regards,
Chandra
Programming is not about using a language to solve a problem, it's about using logic to find a solution !
User avatar
Chandra
Member
Member
Posts: 487
Joined: Sat Jul 17, 2010 12:45 am

Re: Entering protected mode: tutorial disambiguation

Post by Chandra »

guilherme wrote:dw 0FFFFh
dw 00000h
db 00h
db 010010010b
db 010001111b
db 00h
Wrong.

That being stated in the Intel's Manual, the granularity & the operand size must be 0 to be able to use 16- bit code.

Have fun,
Chandra
Last edited by Chandra on Fri Feb 04, 2011 8:51 am, edited 1 time in total.
Programming is not about using a language to solve a problem, it's about using logic to find a solution !
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: Entering protected mode: tutorial disambiguation

Post by Combuster »

Firstly i'm not a ASM noob, i may be a begginer in the NASM compiler, but i have years of experiece on other compilers.
Prove it - A stone might have spent millenia trying to swim but it still sucks at it.
"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 ]
Tosi
Member
Member
Posts: 255
Joined: Tue Jun 15, 2010 9:27 am
Location: Flyover State, United States
Contact:

Re: Entering protected mode: tutorial disambiguation

Post by Tosi »

NASM is not a compiler, it's an assembler. The only time the object code it generates is run "as-is" is for flat-binary files such as bootloaders, or DOS COM programs.
guilherme
Member
Member
Posts: 35
Joined: Mon Jan 31, 2011 6:58 am
Location: Brasil

Re: Entering protected mode: tutorial disambiguation

Post by guilherme »

Ok, i'll test a several of things, i will answer tomorrow.
guilherme
Member
Member
Posts: 35
Joined: Mon Jan 31, 2011 6:58 am
Location: Brasil

Re: Entering protected mode: tutorial disambiguation

Post by guilherme »

Ok (sorry by evering starting replies with Ok, anyway...), i did adjusted the code into a your tips, and each time a adjust it i get an different error.
This code is and simple kernel to backup data form a area of disk to another area on this same disk, encoding contents.
At this time, as the most of the times before, the code boots, displays the "[ ]" in the begginning of screen, and then freezes, ctrl+alt+del don't take any effect, what means that the interrupt flags still off (what was supposed to be like that).
This time, i'll put both the boot and kernel codes, so now everything of this program will be here.
There's more four questions:
1: Can i use 32-bit code without entering protected mode (acessing only base memory), like in the thread "Showstat"?.
2: why do kernel crashes when doing any operation with FS or GS?
3: There's any problem about entering and exiting protected mode without setting segment registers that are not in use, like SS, FS or GS?
4: are the segment registers 16 or 32-bits? if they're 16-bits, how do i can move eax to they? and if they're 32-bit, do i need to move eax to they instead ax, after entering protected mode?

The answer to this questions are a dificcult to find in the web

BOOTCODE:

Code: Select all

[BITS 16]
[Org 0x07C00]
CLI       ;clear interrupts
Xor ax,ax     ;set ax to 0 (in this case, the CS value)
Push ax       ;push 0 from ax
Popf             ;pop 0 from ax into flags register, clearing all flags 
Mov ds,ax    ;set all segment registers to CS (0)
Mov es,ax 
Mov fs,ax
Mov gs,ax
Mov ss,ax
Mov bp,07E00h       ;set stack right after the boot code
Mov sp,07FFEh       ; set top 01FEh bytes after base
RESET:            
Xor ax,ax   ;RESET disk
Mov dx,ax  ; DISK 0 (floppy A:)
Int 013h      ; Call bios interrupt to reset the disk
Jc RESET  ;if any error, try again
Mov ax,0205h     ;READ the FIVE sectors of the code
Mov bx,0500h     ;READ to absolute address 0000h:0500h
Mov cx,0002h     ;READ starting at Cylinder 0, Sector 2 (kernel)
Xor dx,dx             ;READ at head 0, disk 0 (floppy A:)
Int 013h                ; Call bios interrupt to read the disk
Jc RESET          ;if there's some error, jump back to the RESET thread
Jmp 0000h:0500h  ;Go to code
times 510-($-$$) db 000h ;fill with zeroes until byte 510
dw 0AA55h   ;boot key         ;(bytes 511~512)
KERNEL CODE:

Code: Select all

[BITS 16]            
[ORG 0x0500]

;clear interrupt falg

CLI

;Set up flags, segment register and stack pointers:

Xor ax,ax
Push ax
Popf     
Mov ds,ax
Mov ss,ax 
Mov ax,0B800h
Mov es,ax 
Mov bp,STACK
Mov sp,STACK+0200h

;disable text blinking cursor (sometimes the bios enables it before booting)

Mov ah,01h
Mov cx,02B0Bh
Int 010h

;This loop clears the screen, without using Rep Stosw
;but using a block of Stosw's and then a Loop instruction that
;returns to the beggining of this block, this turns the operation
;much faster than a "Rep Stosw"

Xor ax,ax  
Xor di,di
Mov cx,03Eh 
LOOPCLEAR: 
TIMES 020h db 0ABh ;(020h * Stosw)
Loop LOOPCLEAR
TIMES 010h db 0ABh ;(010h * Stosw)


;Once the system booted by floppy, the disk must be reseted before
;being acessed, if the reseting don't work the rest of the code is useless,
;because this means the disk is damaged,
;so the code only proceeds when the disk has been sucessfully reseted.
;In all disk errors therefore, the code will beep three times, reset the disk,
;beep three times again and try again, and, if there's more than five errors, 
;the code will skip the current sector
;those beeps are used to warn me about the errors, and to create a type of
;delay beteween reseting and acessing. 


RESET:
Xor ax,ax
Mov dx,080h
Int 013h
Jnc START
Pusha
Mov ax,0E07h     
Int 010h
Mov ax,0E07h     
Int 010h
Mov ax,0E07h     
Int 010h
Mov ax,0E07h     
Int 010h
Mov ax,0E07h     
Int 010h
Mov ax,0E07h     
Int 010h
Popa
Jmp RESET


;this simply display "[          ]" on the screen.
;that will be used to display the progress 

START:
Mov word  [es:00h],00F5Bh     
Mov word  [es:016h],00F5Dh   

;this is the first thread: read the sectors from the source of the backup, executing 63 loops
;Of 16 sectors each, that fills the memory from 010000h to 08E000h (63*16*512 = 07E000h bytes) 
;and each time the memory gets filled up, it calls a routine that enters protected
;mode, copies the 07E000h bytes from 010000h to 0200000h, and  Adds the address
; to put the data by 07E000h, so each time it happens the data is stored in a different place.
;after that routine return to real-mode and returns to the code, the code reset the buffer to 010000h 
;again and continue copying sectors from disk, this part of copying memory is a second loop, that happens 250 times,
;in a total of 129Mb of bytes copyied (63*16*250*512).

READISK:  
Call RESETEXT 
Mov cx,03Fh  
Mov byte  [COUNTER],0FAh
Mov si,DRD
READLOOP:
Mov ax,04200h
Int 013h
Jc DORESET 
Loop CDRD
Call WRITEEXT
Mov word  [OFFBUFF1],00000h
Mov word  [SEGBUFF1],01000h 
Mov cx,03Fh
Call SHOWSTAT 
Sub byte  [COUNTER],01h 
Jnz READLOOP
Jmp DISCHARGE
DORESET:
Cmp di,05h
Je CDRD      
Pusha    
Mov ax,0E07h     
Int 010h
Mov ax,0E07h     
Int 010h
Mov ax,0E07h     
Int 010h
Xor ax,ax
Mov dx,080h
Int 013h
Mov ax,0E07h     
Int 010h 
Mov ax,0E07h     
Int 010h 
Mov ax,0E07h     
Int 010h 
Popa       
Inc di
Jmp READLOOP
CDRD:
Xor di,di       
Add word  [OFFBUFF1],02000h 
Jnc CONTDRD
Add word  [SEGBUFF1],01000h
CONTDRD: 
Add word  [SECTOR11],010h
Jnc READLOOP
Inc word  [SECTOR21]
Jmp READLOOP


;This is the second thread
;firstly, it encripts the data on buffer of extended memory, calling ENCODE routine
;Then it reset the source and destin variables of the protected mode routines
;So next acesses will acess the begging of this buffer
;the rest of this thread is almost equal to the first one, but:
;the loops read the extended memory to base memory, then writes the data on 
;base memory to disk.
;the disk area to be acessed is different.
;when this loop ends, there is another counter, called MAINCOUNTER,
;this counter is decreased, and if this is nonzero, the code returns to the first thread.
;If zero, this will Halt the processor, and if the HLT fails by some reason, will enter
;a infinite Loop, by jumping in the self Jmp instruction (Jmp $).

DISCHARGE: 
Call ENCODE  
Call RESETEXT
Mov byte  [COUNTER],0FAh
Mov si,DWD
WRITELOOP:  
Call READEXT
Mov word  [OFFBUFF2],00000h
Mov word  [SEGBUFF2],01000h 
Mov cx,03Fh
Call SHOWSTAT 
INLOOP:     
Mov ax,04300h
Int 013h
Jc DOSET 
Loop CDWD
Sub byte  [COUNTER],01h 
Jnz WRITELOOP 
Sub byte  [MAINCOUNTER],01h
Jnz READISK
HLT
Jmp $ 
DOSET:
Cmp di,05h
Je CDWD     
Pusha    
Mov ax,0E07h     
Int 010h
Mov ax,0E07h     
Int 010h 
Mov ax,0E07h     
Int 010h
Xor ax,ax
Mov dx,080h
Int 013h
Mov ax,0E07h     
Int 010h
Mov ax,0E07h     
Int 010h
Mov ax,0E07h     
Int 010h
Popa       
Inc di
Jmp INLOOP
CDWD:
Xor di,di       
Add word  [OFFBUFF2],02000h 
Jnc CONTDWD
Add word  [SEGBUFF2],01000h
CONTDWD: 
Add word  [SECTOR12],010h
Jnc INLOOP
Inc word  [SECTOR22]
Jmp INLOOP   


;this routine Push falgs, genreal registers, DS e ES registers, enter
;protecte mode, move data from base memory to extended memory, get back in real-mode,
;pop everything that has been pushed and returns.
;note the this and the next routines won't use the stack, so SS, EBP and ESP don't matter.


WRITEEXT:
Pushf
Pusha
Push ds
Push  es
Xor ax,ax 
Mov ds,ax
Mov es,ax
lgdt [GDTP]          
Mov eax,CR0           
Or eax,01h      
Mov CR0,eax    
Jmp 08h:CLEARA
[BITS 32]           
CLEARA:           
Mov ax,010h       
Mov ds,ax
Mov es,ax
Mov esi,010000h
Mov edi,[LASTDESTIN]
Mov ecx,01F800h
Rep Movsd
Mov [LASTDESTIN],edi
Jmp 018h:REALA
[BITS 16]      
REALA: 
Mov ax,020h
Mov ds,ax
Mov es,ax
Mov eax,CR0           
Xor eax,01h      
Mov CR0,eax    
Jmp 0000h:REALB
REALB:
Pop es
Pop ds
Popa
Popf
Ret

;this is routine is the same and WRITEEXT, but do de inverse operation about the direction
; of data moving (EX to BASE).

READEXT:
Pushf
Pusha
Push ds
Push  es
Xor ax,ax
Mov ds,ax
Mov es,ax
lgdt [GDTP]          
Mov eax,CR0           
Or eax,01h      
Mov CR0,eax    
Jmp 08h:CLEARB
[BITS 32]           
CLEARB:           
Mov ax,010h       
Mov ds,ax
Mov es,ax
Mov edi,010000h
Mov esi,[LASTSOURCE]
Mov ecx,01F800h
Rep Movsd
Mov [LASTSOURCE],esi
Jmp 018h:REALC
[BITS 16]      
REALC: 
Mov ax,020h
Mov ds,ax
Mov es,ax
Mov eax,CR0           
Xor eax,01h      
Mov CR0,eax    
Jmp 0000h:REALD
REALD:
Pop es
Pop ds
Popa
Popf
Ret




;this routine do the same about pushing, entering proteced mode, getting back to real-mde
;and poping everything, but this don't move nothing, just encript the data in extended memory 
;by Adding the First dword by the Second and Adding offset by 4, until reach the dword before
;the last, the last dword is leave intact.

ENCODE:
Pushf
Pusha
Push ds
Push  es
Xor ax,ax 
Mov ds,ax
Mov es,ax
lgdt [GDTP]          
Mov eax,CR0           
Or eax,01h      
Mov CR0,eax    
Jmp 08h:CLEARC
[BITS 32]           
CLEARC:           
Mov ax,010h       
Mov ds,ax
Mov es,ax
Mov ebx,0200000h
LOOPENCODE:
Mov eax,[ebx+04h]
Add [ebx],eax
Add ebx,04h
Cmp ebx,07D0C000h
Jb LOOPENCODE
Jmp 018h:REALE
[BITS 16]      
REALE: 
Mov ax,020h
Mov ds,ax
Mov es,ax
Mov eax,CR0           
Xor eax,01h      
Mov CR0,eax    
Jmp 0000h:REALF
REALF:
Pop es
Pop ds
Popa
Popf
Ret


;this routine simply reset values of LASTSOURCE and LASTDESTIN
;and it don't need to enter protected mode, just need to be 32-bit code.

[BITS 32]    
RESETEXT:
Pushf
Push eax
Mov eax,0200000h
Mov [LASTDESTIN],eax
Mov [LASTSOURCE],eax
Pop eax
Popf
Ret

;this routine simply increase the dword of progress, turn it on decimal code
;and display it inside the "[          ]" that has been displayed on screen.
;As the routine before, only need to be 32-bit, not protected mode.

SHOWSTAT:  
Pushf
Pusha        
Mov edi,02h
Inc dword  [PRGCOUNTER]
Mov eax,[PRGCOUNTER]
Mov ebx,03B9ACA00h
Xor edx,edx
Div ebx
Add ax,0F30h
Stosw
Mov eax,edx
Mov ebx,05F5E100h
Xor edx,edx
Div ebx
Add ax,0F30h
Stosw
Mov eax,edx
Mov ebx,0989680h
Xor edx,edx
Div ebx
Add ax,0F30h
Stosw
Mov eax,edx
Mov ebx,0F4240h
Xor edx,edx
Div ebx
Add ax,0F30h
Stosw
Mov eax,edx
Mov ebx,0186A0h
Xor edx,edx
Div ebx
Add ax,0F30h
Stosw
Mov eax,edx
Mov ebx,02710h
Xor edx,edx
Div ebx
Add ax,0F30h
Stosw
Mov eax,edx
Mov ebx,03E8h
Xor edx,edx
Div ebx
Add ax,0F30h
Stosw
Mov eax,edx
Mov ebx,064h
Xor edx,edx
Div ebx
Add ax,0F30h
Stosw
Mov eax,edx
Mov ebx,0Ah
Xor edx,edx
Div ebx
Add ax,0F30h
Stosw
Mov ax,dx
Add ax,0F30h
Stosw
Popa
Popf
Ret     

;this is the DAP of the backup source disk area (note that both source and destin are in the same disk)

DRD: 
dd 00100010h
OFFBUFF1 dw 00000h
SEGBUFF1 dw 01000h
SECTOR11 dw 0000h
SECTOR21 dw 0000h     
dd 00000000h

;this is the DAP of the backup destin disk area 

DWD:
dd 00100010h
OFFBUFF2 dw 00000h
SEGBUFF2 dw 01000h
SECTOR12 dw 04E4Ch
SECTOR22 dw 063Eh    
dd 00000000h

;this are the variables used during code
  
MAINCOUNTER db 0A6h  
PRGCOUNTER dd 00000000h
COUNTER db 0FAh

LASTDESTIN dd 00200000h
LASTSOURCE dd 00200000h

;this is the GDT, there's the description of it:
;the first two entries after null entrie are 32-bit code and data segment,
;the take the whole addressable space, are unconforming, readable/writeable
;system ring, and the two entries next are the same, but 16-bit.


GDT:  

dq 00000000000000000h  

dw 0FFFFh  
dw 00000h
db 00h   
db 010011010b 
db 011001111b
db 00h   

dw 0FFFFh  
dw 00000h
db 00h   
db 010010010b 
db 011001111b
db 00h  

dw 0FFFFh  
dw 00000h
db 00h   
db 010011010b 
db 000001111b
db 00h   

dw 0FFFFh  
dw 00000h
db 00h   
db 010010010b 
db 000001111b
db 00h  

;GDT pointer

GDTP:                           
dw GDTP-GDT-1        
dd GDT     

;1024 bytes stack

STACK:
TIMES 0100h dd 00000000h
User avatar
DavidCooper
Member
Member
Posts: 1150
Joined: Wed Oct 27, 2010 4:53 pm
Location: Scotland

Re: Entering protected mode: tutorial disambiguation

Post by DavidCooper »

guilherme wrote:At this time, as the most of the times before, the code boots, displays the "[ ]" in the begginning of screen, and then freezes, ctrl+alt+del don't take any effect, what means that the interrupt flags still off (what was supposed to be like that).
This time, i'll put both the boot and kernel codes, so now everything of this program will be here.
It's just after the [ ] part that you try to load 129MB in from a 1.44MB floppy disk. I don't know why you want to load in 63 x 16 x 250 x 512 bytes, but there are 18 sectors x 2 sides x 80 tracks x 512 bytes on a floppy disk. Why don't you get something up and running in the first 64KB of memory before you try to export megabytes of unnecessary junk into high memory so that you can see what you're doing more easily first?

[Edit: sorry about that bit - you were actually loading them in from some other device and not the floppy disk. I'm still not clear as to what you're trying to do, but you're actually a lot more capable than I had thought from all the mistakes you're posting all over the forum.]
There's more four questions:
1: Can i use 32-bit code without entering protected mode (acessing only base memory), like in the thread "Showstat"?.
2: why do kernel crashes when doing any operation with FS or GS?
3: There's any problem about entering and exiting protected mode without setting segment registers that are not in use, like SS, FS or GS?
4: are the segment registers 16 or 32-bits? if they're 16-bits, how do i can move eax to they? and if they're 32-bit, do i need to move eax to they instead ax, after entering protected mode?
1. No. The code in the Showstat thread which I haven't seen must work by magic if it does that.
2. Don't know - I never use them.
3. Until you use instructions that depend on them there is no problem.
4. Segment registers are 16-bit. I don't use assembler (because I work directly with machine code instead), but I imagine you should use mov ss,ax as in real mode.
Last edited by DavidCooper on Sun Feb 06, 2011 11:48 pm, edited 2 times in total.
Help the people of Laos by liking - https://www.facebook.com/TheSBInitiative/?ref=py_c

MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming
User avatar
Chandra
Member
Member
Posts: 487
Joined: Sat Jul 17, 2010 12:45 am

Re: Entering protected mode: tutorial disambiguation

Post by Chandra »

You are impossible.

Did you try to isolate the problem before writing such a heavy routine? Your code never worked as intended and then you are adding more and more and more stuffs. Man, wake up- it's too late.
guilherme wrote:1: Can i use 32-bit code without entering protected mode (acessing only base memory), like in the thread "Showstat"?.
In my previous post (page 1), I did mention about 'Unreal Mode'.I realized that you ignored my post because you are simply obsessive with what you want to do and never care anything else.

And this is another source of error.
guilherme wrote:

Code: Select all

GDT: 

dq 00000000000000000h 

dw 0FFFFh 
dw 00000h
db 00h 
db 010011010b 
db 011001111b
db 00h 

dw 0FFFFh 
dw 00000h
db 00h 
db 010010010b 
db 011001111b
db 00h 

dw 0FFFFh 
dw 00000h
db 00h 
db 010011010b 
db 000001111b
db 00h 

dw 0FFFFh 
dw 00000h
db 00h 
db 010010010b 
db 000001111b
db 00h 

;GDT pointer

GDTP: 
dw GDTP-GDT-1 
dd GDT 
The last two entries are fine but what about the 32 bit code and data? Why are you setting up the limit to 0xFFFF when you want to do extended memory operations? I guess the result is 'General Protection Fault'.

At the very least,you should be able to do the following before throwing a huge bunch of the code and asking us to isolate the problem.

1. Understand GDT very well.
2. Grab Bochs and emulate your code in it. When anything goes wrong, you can simply pick up the cause of the errror from Bochs' log.
3. Write a code that can successfully switch to protected mode and then return to real mode.For this,
- Write a bootloader.
- Write a simple real mode test kernel.
- Write a simple protected mode test kernel
- Load the real mode kernel to address 0x1000 and the protected mode kernel to address 0x100000 (from the bootloader).
- From within the bootloader, enter protected mode and then jump to protected mode kernel.
- When you are sure your 'protected mode test kernel' is working as intended, jump to real mode kernel (from protected mode kernel).
- Write a routine to switch to real mode inside the 'real mode test kernel'.Then issue a BIOS interrupt to print a character to make sure the switch is successfull.
4. All done, when you succeed, you are now ready to play with your own code.
5. Go on adding stuffs one by one.This way, you can track down what is causing the error.

Best of Luck,
Chandra
Programming is not about using a language to solve a problem, it's about using logic to find a solution !
guilherme
Member
Member
Posts: 35
Joined: Mon Jan 31, 2011 6:58 am
Location: Brasil

Re: Entering protected mode: tutorial disambiguation

Post by guilherme »

I already have tried to isolate that, and already did some sucessfull protected mode kernels, and kernels that switch between real and protected mode.
Now, just a ask:
Why you think the limit is set to 0FFFFh?
The limit is set to 0FFFFFh, with granularity of 4Kb, so the real limit is 0FFFFFFFFh, this is, the full adressable memory.
User avatar
Chandra
Member
Member
Posts: 487
Joined: Sat Jul 17, 2010 12:45 am

Re: Entering protected mode: tutorial disambiguation

Post by Chandra »

guilherme wrote:I already have tried to isolate that, and already did some sucessfull protected mode kernels, and kernels that switch between real and protected mode.
Now, just a ask:
Why you think the limit is set to 0FFFFh?
The limit is set to 0FFFFFh, with granularity of 4Kb, so the real limit is 0FFFFFFFFh, this is, the full adressable memory.
And where is fffffh? I can see ffffh only?

Cheers
Programming is not about using a language to solve a problem, it's about using logic to find a solution !
Post Reply