home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / ASM / PMTUT002.ZIP / SIMPL_PM.ASM < prev   
Encoding:
Assembly Source File  |  1995-09-19  |  3.8 KB  |  155 lines

  1. ;----
  2. ;    Example program switching to Protected and back to Real Mode
  3. ;    Jerzy Tarasiuk                    8-Jun-1995
  4. ;
  5. code    segment
  6.     assume    cs:code
  7. stk    segment    para stack 'stack'
  8.     dw    100h dup(?)
  9. stk    ends
  10.     assume    cs:code,ss:stk,ds:Nothing,es:Nothing
  11.     .386P
  12.  
  13. ;-
  14. ;    GDT to be used in Protected Mode
  15. ;
  16. mygdt    dq    0        ; null descriptor
  17. gdtcd    dw    -1,0,9A00h,0     ; 64kB code segment, base to be set
  18.     dw    -1,0,9200h,008Fh ; 4GB R/W segment, base=0
  19.     dw    -1,0,9200h,0     ; 64kB R/W segment, base=0
  20.  
  21. ;---
  22. ;    pm_mem    - access memory (peek/poke a byte) in Protected Mode
  23. ;
  24. ;    entry    EBX=address, CX=0 for peek to CL or CX!=0 for poke CL
  25. ;    changes    EAX,EDX,GDTR,CL
  26. ;
  27. ;    requires A20 to be enabled if to be used on a PC compatible
  28. ;    (A20 is usually enabled if DOS is loaded into HMA)
  29. ;
  30. pm_mem    proc
  31.     pushf
  32.     push    ds
  33.     mov    ax,cs
  34.     movzx    eax,ax
  35.     shl    eax,4        ; eax=base for code segment
  36.     mov    dword ptr gdtcd[2],eax
  37.     mov    byte ptr gdtcd[5],9Ah ; set segment attribute
  38.     mov    dx,offset mygdt
  39.     movzx    edx,dx
  40.     add    eax,edx        ; eax=base for GDT
  41.     push    eax
  42.     push    20h
  43.     movzx    eax,sp        
  44.     cli            ; make sure no ISR will interfere now
  45.     lgdt    fword ptr ss:[eax] ; LGDT is necessary before switch to PM
  46.     add    sp,6
  47.     mov    eax,cr0
  48.     or    al,1
  49.     mov    cr0,eax        ; sets Protected Mode
  50.     db    0eah        ; far jump to set CS & clear prefetch queue
  51.     dw    pm_in
  52.     dw    8
  53. pm_in:    mov    dx,10h
  54.     mov    ds,dx        ; load long segment descriptor from GDT into DS
  55.     jcxz    pm_get
  56.     mov    [ebx],cl
  57. pm_get:    mov    cl,[ebx]
  58.     mov    dl,18h
  59.     mov    ds,dx        ; load 64kB segment descriptor from GDT into DS
  60.     and    al,not 1
  61.     mov    cr0,eax        ; sets Real Mode
  62.     db    0eah        ; far jump to restore CS & clear prefetch queue
  63.     dd    pm_out        ; it MUST be jump - far return crashed!
  64. pm_out:    pop    ds
  65.     popf
  66.     ret
  67. pm_mem    endp
  68.  
  69. ;---
  70. ;    vfycpu    - make sure have proper CPU, in Real Mode, and A20 enabled
  71. ;
  72. ;    changes    AX,DX
  73. ;    returns AL=error code if anything wrong
  74. ;    error codes:    040h    - not 32-bit CPU (PM,A20 not tested)
  75. ;            001h    - already in PM (386+, A20 not tested)
  76. ;            0FFh    - A20 disabled (32-bit CPU in RM)
  77. ;
  78. vfycpu    proc
  79.     pushf            ; save flags
  80.     cli            ; make sure no ISR will interfere now
  81. ;
  82.     pushf            ; 1. make sure have at least 386
  83.     pop    ax        ; AX=flags
  84.     xor    ah,40h        ; toggle NT
  85.     push    ax        ; stack: modified_flags,original_flags
  86.     popf
  87.     pushf            ; stack: modified_flags_from_cpu,original_flags
  88.     pop    dx        ; DX=flags passed via CPU
  89.     mov    al,dh
  90.     xor    al,ah
  91.     jnz    vcfail        ; improper CPU
  92. ;
  93.     smsw    ax        ; 2. make sure are in Real Mode
  94.     and    al,1
  95.     jnz    vcfail        ; if already in PM (maybe VM86)
  96. ;
  97.     push    ds        ; 3. make sure A20 is enabled
  98.     push    es
  99.     push    bx
  100.     xor    bx,bx
  101.     mov    ds,bx
  102.     mov    ax,-1
  103.     mov    es,ax
  104.     xor    [bx],ah        ; change byte[000000h]
  105.     mov    al,es:[bx+10h]    ; get byte[100000h]
  106.     xor    [bx],ah        ; change byte[000000h]
  107.     xor    al,es:[bx+10h]    ; compare byte[100000h] with its previous value
  108.                 ; 0 if unchanged, -1 means [000000h]==[100000h]
  109.     pop    bx
  110.     pop    es
  111.     pop    ds
  112. ;
  113. vcfail:    popf            ; restore flags
  114.     test    al,al        ; test error code
  115.     ret
  116. vfycpu    endp
  117.  
  118. ;---
  119. ;    sample program
  120. ;    - check if have proper CPU, exit with error message if bad
  121. ;    - peek byte[0FFFFFFF0h] in PM
  122. ;    - peek byte[0FFFEFFF0h] in PM
  123. ;    - exit (status = byte obtatained)
  124. ;
  125. badcpum    db    "Not 80386+ CPU!",0Dh,0Ah,'$'
  126. inpmerm    db    "Already in Protected Mode!",0Dh,0Ah,'$'
  127. bada20m    db    "Address line A20 disabled!",0Dh,0Ah,'$'
  128.  
  129. start:    call    vfycpu        ; make sure having proper CPU and mode
  130.     add    al,al
  131.     jz    cpuok        ; .. OK
  132.     lea    dx,bada20m
  133.     jc    error
  134.     lea    dx,badcpum
  135.     js    error
  136.     lea    dx,inpmerm
  137. error:    push    cs        ; not proper - error message and exit
  138.     pop    ds
  139.     mov    ah,9
  140.     int    21h
  141.     mov    ax,4cffh    ; exit, status=-1
  142.     int    21h
  143.  
  144. cpuok:    xor    cx,cx        ; peek a byte
  145.     mov    ebx,-10h    ; from 0FFFFFFF0h
  146.     call    pm_mem
  147.     xor    cx,cx        ; peek a byte
  148.     mov    ebx,-10010h    ; from 0FFFEFFF0h
  149.     call    pm_mem
  150. exit:    mov    ah,4ch        ; exit
  151.     mov    al,cl        ; status = the byte
  152.     int    21h
  153. code    ends
  154.     end    start
  155.