Why does my PC restart in switching p-mode and r-mode?

Started by leetow2003, November 25, 2010, 02:39:42 AM

Previous topic - Next topic

leetow2003

I want to test entering protected mode and returning
to real mode,but when I run program,my PC always
restart,Why does my PC restart,and how to correct it,
Look:

jump16   macro  selector,offsetv
                 db     0eah       ;jmp
    dw     offsetv   ;2 bytes offset address
    dw     selector 
    endm

jump32   macro  selector,offsetv
              db     0eah     
              dd     offsetv   ;4 bytes offset address
              dw     selector 
             endm

;
descriptor  struc
limitl          dw   0       
basel         dw   0       
basem       db   0       
attributes  dw   0       
baseh       db   0       
descriptor  ends

;
pdesc       struc
limit         dw   0       
base        dd   0       
pdesc       ends

          .386P
;---------------------------------
dseg        segment   use16     
gdt         label   byte       
dummy       descriptor <>       
code32_sel  = 08h               
code32      descriptor <0ffffh,,,4098h,>
gdtlen      = $-gdt
;
vgdtr        pdesc <gdtlen-1,>   
dseg         ends

;----------------------
;
cseg1       segment   use16   
              assume  cs:cseg1, ds:dseg
start:     
            mov ax,dseg
            mov ds,ax
            ;
            mov bx,16
           mul bx             
           add ax,offset gdt 
           adc dx,0
           mov word ptr vgdtr.base,ax
           mov word ptr vgdtr.base+2,dx
            ;
           mov ax,cseg2           
           mul bx
           mov code32.basel,ax   
           mov code32.basem,dl   
           mov code32.baseh,dh
            ;
           lgdt  fword ptr vgdtr   
           ;
           cli                 
           call ea20           
          ;
          mov eax,cr0
          or eax,1
          mov cr0,eax
         ;Enter protected mode
         jump32  <code32_sel>,<offset spm32>
         ;
toreal:     
         call da20           
         sti
         mov ah,4ch
         int 21h           
         ;
;
ea20        proc
              push  ax
              in    al,92h
             or    al,2
             out   92h,al
             pop   ax
             ret
ea20        endp
;
;
da20        proc
               push  ax
               in    al,92h
              and   al,0fdh     ;0fdh=not 20h
              out   92h,al
              pop   ax
              ret
da20        endp
cseg1       ends
;---------------------------------
cseg2       segment   use32   
               assume  cs:cseg2
      
spm32:     
            mov eax,cr0
           and eax,0fffffffeh
            mov cr0,eax
            ;Return to real mode
            jump16 <seg toreal>,<offset toreal>
            ;

cseg2    ends
;--------------------------
            end start


japheth


leetow2003,

You'll have to find a way to analyze your programs yourself and detect why they don't work as expected.
If you want to learn, it's not a good strategy just to post your programs and expect others to find the errors.

Good strategies are:


  • find a debugger which allows you to step through your mode-switching stuff. Have a look at Bochs!
  • add "display" code to your program, which works in both real- and protected-mode. You should consider to access the text-mode screen at B800:0000 directly.
 
That said, in your program, your macro jump32 is faulty. How is the cpu to know that you want a 32--bit jump there? Make yourself familiar with the 0x66 prefix!

leetow2003

I am a novice,so I hope you can help me.
who could give me an example,the function of this example
only switch two modes,that it enters in 32-bit protected mode form real
mode,and then return back to real mode.Thank you very much.

Gunther

Quote from: leetow2003, November 25, 2010, at 01:11:34 PMI am a novice,so I hope you can help me.

leetow2003,

I would like to underline japheth's statement. Moreover, for a novice, Protected Mode isn't the right playground, because system programming (that's what we speaking about) is really complicated stuff.

Quote from: leetow2003, November 25, 2010, at 01:11:34 PMwho could give me an example...

That technique isn't really necessary, because normal program termination via INT 21h is good enough. The only example that I have is 15 year old code for PowerBASIC. So, you must be familiar with PB 3.5 and TASM 4.1 (assembly language part). You can download the application from the PB site.

To your posted code: Another alternative as debugger is DEBUGX. It's a well written and good maintained tool; you can download it here: http://www.japheth.de/. Trace step by step through the code and you'll learn a lot.

Gunther
Forgive your enemies, but never forget their names.

leetow2003

I am sorry,maybe waht I said was ambiguous.In fact I have
learned 8088 for a long time,but I learned 80386 not long ago,
so I am not familiar with protected mode,and I am interested
in it,so I asked some questions about it.I have downloaded
the tool debugx,but I find:for the same example,I compiled
it using masm 5.1 and tasm 3.0 respectively,and debugged the
exe file using debugx and debug32 respectively,a few instructions
aren't alike after unassemble.At last I compiled it using tasm 4.1,
but system prompt there are a lack of files,such as DPMI16BI.ovl,
DPMILOAD.exe,and so on.
I want to know what software you compile 80386 codes,and what files
you need.
Thank you very much.

japheth

Quote from: leetow2003 on November 26, 2010, 05:55:27 AM
and debugged the
exe file using debugx and debug32 respectively,a few instructions
aren't alike after unassemble.

Obviously.

Quote
At last I compiled it using tasm 4.1,
but system prompt there are a lack of files,such as DPMI16BI.ovl,
DPMILOAD.exe,and so on.

So you thought that you can solve the problem by using another assembler?

It might sound a bit offending, but that is very unwise IMO.

Instead you should have used your brain and learnt the intel JMP instruction.

I also used DEBUGX with your program. It tells:


D:\Test>debugx code303.exe
-u
14A4:0000 B8A214            MOV     AX,14A2
14A4:0003 8ED8              MOV     DS,AX
14A4:0005 BB1000            MOV     BX,0010
14A4:0008 F7E3              MUL     BX
14A4:000A 050000            ADD     AX,0000
14A4:000D 83D200            ADC     DX,+00
14A4:0010 A31200            MOV     [0012],AX
14A4:0013 89161400          MOV     [0014],DX
14A4:0017 B8AA14            MOV     AX,14AA
14A4:001A F7E3              MUL     BX
14A4:001C A30A00            MOV     [000A],AX
14A4:001F 88160C00          MOV     [000C],DL
-u
14A4:0023 88360F00          MOV     [000F],DH
14A4:0027 0F01161000        LGDT    [0010]
14A4:002C FA                CLI
14A4:002D E81900            CALL    0049
14A4:0030 0F20C0            MOV     EAX,CR0
14A4:0033 6683C801          OR      EAX,+01
14A4:0037 0F22C0            MOV     CR0,EAX
14A4:003A EA00000000        JMP     0000:0000
14A4:003F 0800              OR      [BX+SI],AL
14A4:0041 E80E00            CALL    0052
-


and I can instantly see - with one glance - the problem: JMP 0000:0000. And no, it's NOT the fault of the assembler or DEBUGX, it's a simple error in your program.


Gunther

leetow2003,

as japheth pointed out: there is at least one simple error in your program. It's easy to switch into 32 bit Protected Mode:


       cli ;disable interrupts
       mov eax,cr0 ;eax = content of Control Register 0
       or al,1 ;set PM bit
       mov cr0,eax ;switch to Protected Mode
       jmp PMODE ;flush the processor's prefetch queue

       PMODE:
       sti ;enable interrupts


That should give you the idea.

Gunther
Forgive your enemies, but never forget their names.

BogdanOntanu

Quote from: Gunther on November 26, 2010, 02:10:15 PM
leetow2003,

as japheth pointed out: there is at least one simple error in your program. It's easy to switch into 32 bit Protected Mode:


       cli ;disable interrupts
       mov eax,cr0 ;eax = content of Control Register 0
       or al,1 ;set PM bit
       mov cr0,eax ;switch to Protected Mode
       jmp PMODE ;flush the processor's prefetch queue

       PMODE:
       sti ;enable interrupts


That should give you the idea.

Gunther


One should NOT enable interrupts before having a valid IDT table (and handlers) setup... and you also need to reprogram the PIC (or APIC) controller...
Ambition is a lame excuse for the ones not brave enough to be lazy.
http://www.oby.ro

Gunther

Quote from: BogdanOntanu, November 26, 2010, at 02:13:52 PMOne should NOT enable interrupts before having a valid IDT table (and handlers) setup...

You're right. The above code was written from scratch and I've forgotten the following line:


       cli ;disable interrupts
       mov eax,cr0 ;eax = content of Control Register 0
       or al,1 ;set PM bit
       mov cr0,eax ;switch to Protected Mode
       jmp PMODE ;flush the processor's prefetch queue

       PMODE:
      ...                       ;other necessary operations in PM
       sti ;enable interrupts


The crucial point is the jump.

Gunther
Forgive your enemies, but never forget their names.

japheth

Quote from: Gunther on November 26, 2010, 02:10:15 PM
It's easy to switch into 32 bit Protected Mode:


       jmp PMODE ;flush the processor's prefetch queue

       PMODE:


It's easy, but it's not THAT easy. To switch from real-mode to 32-bit protected mode you need an inter-segment jump (from a USE16 to a USE32 segment). Your sample code won't do that.

The opposite direction, from 32-bit protected-mode to 16-bit real-mode, is a bit more complicated, because you'll have to switch to a 16-bit protected-mode code segment first, to set the proper attributes for CS, before switching to real-mode.


Gunther

Quote from: japheth, November 26, 2010, at 06:55:59 PMTo switch from real-mode to 32-bit protected mode you need an inter-segment jump

Or an appropriate RETF without CALL. Both ways are possible. And yes, the above short code snippet enables only 16 bit PM.

Quote from: japheth, November 26, 2010, at 06:55:59 PMThe opposite direction, from 32-bit protected-mode to 16-bit real-mode, is a bit more complicated, ...

In any case, one will need valid selectors/descriptors for both: the 16 and the 32 bit segments. Assuming you have that, it's not so hard to switch back from 32 bit segment to the 16 bit segment, where you can finish the program via INT 21h.

Gunther
Forgive your enemies, but never forget their names.

leetow2003

Thank all of you,although I haven't solved this problem,
I must thank all of you for helping me.I will continue
learning more knowledge,I hope you will continue helping
me.Thank you,thank you you very much.