My PC always restart when I call another sub-program in P-M

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.
Post Reply
leetow2003
Member
Member
Posts: 70
Joined: Fri Nov 19, 2010 6:54 pm

My PC always restart when I call another sub-program in P-M

Post by leetow2003 »

I want to call another sub-program in P-Mode,how to correct?
Look:

Code: Select all

I define Macro:
;
call16 macro selector,offsetv
        db 9ah ;CALL
        dw offsetv ;offset
        dw selector ;selector
       endm
;and in GDT:
dseg segment use16 
  gdt label byte 
  dummy descriptor <> 
....

  codes descriptor <0ffffh,,,98h,>
  codes_sel =codes-gdt ;sub-program
....
dseg ends
;Sub-Program
cseg1 segment use16
  assume cs:cseg1
dspmsg:
  ;I write nothing,only instruction ret
  ret
cseg1 ends

;In my main program
  mov bx,16
  mov ax,cseg1
  mul bx
  mov codes.basel,ax ;set the sub-program
  mov codes.basem,dl 
  mov codes.baseh,dh   
  ;In P-mode
  call16 codes_sel,dspmsg
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: My PC always restart when I call another sub-program in

Post by Brendan »

Hi,

While I don't agree with "Just use C" (partly because most C compilers can't/won't support "call far"); if you intend to use assembly then you should find an assembler that is capable of assembling. Any 80x86 assembler that can't handle an instruction that has been around since 8086 (like "call far") is not an assembler that is worth bothering with. Of course it's entirely possible that the assembler you're using isn't a steaming pile of camel puke, and that the reason your "call16" macro exists is because you have no idea how to use your assembler. In that case, learn to use your assembler... ;)

Also note that if you use a "call far" instruction (which pushes a "return CS" and "return eIP" on the stack), then you have to return with a "return far" instruction (that returns to the CS:eIP" that is on the stack). If you use a normal "return near" then you'll end up returning to the wrong code segment with a corrupt stack.

If using the wrong type of "ret" isn't the problem, then the problem could be anything else (including your GDT, your "lgdt" instruction, your stack, your memory management, etc).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
leetow2003
Member
Member
Posts: 70
Joined: Fri Nov 19, 2010 6:54 pm

Re: My PC always restart when I call another sub-program in

Post by leetow2003 »

Brendan wrote:Hi,

While I don't agree with "Just use C" (partly because most C compilers can't/won't support "call far"); if you intend to use assembly then you should find an assembler that is capable of assembling. Any 80x86 assembler that can't handle an instruction that has been around since 8086 (like "call far") is not an assembler that is worth bothering with. Of course it's entirely possible that the assembler you're using isn't a steaming pile of camel puke, and that the reason your "call16" macro exists is because you have no idea how to use your assembler. In that case, learn to use your assembler... ;)

Also note that if you use a "call far" instruction (which pushes a "return CS" and "return eIP" on the stack), then you have to return with a "return far" instruction (that returns to the CS:eIP" that is on the stack). If you use a normal "return near" then you'll end up returning to the wrong code segment with a corrupt stack.

If using the wrong type of "ret" isn't the problem, then the problem could be anything else (including your GDT, your "lgdt" instruction, your stack, your memory management, etc).


Cheers,

Brendan
Hi:
My assembler is masm 5.1,I don't define stack segment in GDT,must I define stack?
I change "ret" to "ret far" or "retf far",but the PC also restart.
There are my codes:

Code: Select all

;Jmp Macro
jump     macro  selector,offsetv
         db     0eah     
         dw     offsetv   
         dw     selector  
        endm

;Call Macro
call16  macro selector,offsetv
         db     09ah       
         dw     offsetv   
         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 <>       

code        descriptor <0ffffh,,,98h,>
code_sel    =code-gdt           

codes       descriptor <0ffffh,,,98h,>
codes_sel   =codes-gdt         ;sub-program

gdtlen      =$-gdt
;
vgdtr        pdesc <gdtlen-1,>   
;
dseg         ends

;-------------------------------------------------------------
;subprogram
cseg1     segment  use16
          assume cs:cseg1
dspmsg:
           ret far
cseg1     ends
;------------------------------------------
cseg        segment   use16     
            assume  cs:cseg, 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,cs
     mul bx
     mov code.basel,ax    
     mov code.basem,dl    
     mov code.baseh,dh
     ;
     mov ax,cseg1
     mul bx
     mov codes.basel,ax   
     mov codes.basem,dl    
     mov codes.baseh,dh
     ;
     lgdt  fword ptr vgdtr
     ;
     cli                  
     call ea20           
     ;
     mov eax,cr0
     or eax,1
     mov cr0,eax
     ;
     jump <code_sel>,<offset virtual>
     ;
virtual:   
     call16 codes_sel,dspmsg  ;call sub-program
     ;
     mov eax,cr0
     and eax,0fffffffeh
     mov cr0,eax
     ;
     jump <seg real>,<offset real>
     ;
real:       
     call da20            
     sti    
     mov  ax,4c00h        
     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

;
cseg        ends
            end  start

User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: My PC always restart when I call another sub-program in

Post by Brendan »

Hi,
leetow2003 wrote:My assembler is masm 5.1,I don't define stack segment in GDT,must I define stack?
I don't know much about MASM, but "CALL far ptr dspmsg" should work (if the code you're calling has a correct "assume cs:???" directive before it).

You have to have a valid stack; but normally you'd use the same descriptor in the GDT for SS and DS (and ES, FS, GS) rather than having a special descriptor just for SS.
leetow2003 wrote:I change "ret" to "ret far" or "retf far",but the PC also restart.
A quick checklist:
  • Is your stack correct
  • Are your GDT entries correct
  • Is your "lgdt" instruction (and the data it loads) correct
  • Is the code to switch to protected mode sane (e.g. sets all segment registers to "protected mode compatible" values)
  • Are you writing 16-bit code when you need 32-bit code
  • Did you leave interrupts enabled when you shouldn't
  • Did you use a BIOS function when you shouldn't (e.g. in protected mode)
  • Is all of your code and data loaded into memory correctly (e.g. maybe only the first 512 bytes of a 2058 byte program is loaded)
  • Are you relying on uninitialized values somewhere
  • Is your memory management correct (e.g. maybe you accidentally use an area of ROM as RAM or something)
Basically what I'm trying to say is that there's about 3.382 million possible problems, and the code and other information you've provided rules out about 3 of them, which only leaves about 3.382 million possible problems. Note: I may have mis-counted them(!) ;)


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Post Reply