home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_02_10 / 2n10038a < prev    next >
Text File  |  1991-08-27  |  35KB  |  1,197 lines

  1.     Page    60,132
  2. ;---------------------------------------------------------------
  3. ;               BEGIN LISTING 2
  4. ;---------------------------------------------------------------
  5. ;
  6. ; 386LOAD.ASM    Copyright (c) 1991 Robert Collins
  7. ;
  8. ;    This program demonstrates various aspects of CPU
  9. ;    behavior that become apparent when using LOADALL.
  10. ;
  11. ;    Test 1:  Checks that LOADALL loads all the general-
  12. ;         purpose registers; loads the segment registers
  13. ;         with values that are inconsistant to their
  14. ;         respective descriptor cache registers.
  15. ;
  16. ;    Test 2:  Access extended memory in real mode.
  17. ;
  18. ;    Test 3:  Tests that the Present bit in a descriptor
  19. ;         table can be loaded using LOADALL without
  20. ;         generating exception 11.  But when the segment
  21. ;         is accessed, exception 13 is generated.
  22. ;         NOTE:    This test should be done in protected
  23. ;         mode, but can be done in real mode.  1) In real
  24. ;         mode, no error code is pushed on the stack
  25. ;         (possibly due to a bug in the CPU).  2) Also,
  26. ;         when this test is executed in real-mode, the
  27. ;         '386 fails to set the Present bit when the
  28. ;         segment is subsequently loaded.  This latter
  29. ;         condition is clearly a bug in the '386.
  30. ;
  31. ;    Test 4:  Test 32-bit protected mode.
  32. ;
  33. ;    Test 5:  Test 32-bit real mode -- a mode that is an
  34. ;         illegal mode for the CPU.
  35. ;
  36. ;    Test 6:  Test that the Granularity bit in the descriptor
  37. ;         cache register has no affect on the segment
  38. ;         limit field.
  39. ;
  40. ;    Test 7:  Test execution breakpoints.
  41. ;
  42. ;    Test 8:  Test data breakpoints.
  43. ;
  44. ;    This program was written for Microsoft MASM 5.1.
  45. ;    This program contains compiler directives and branching
  46. ;    techniques that might not be available on previous
  47. ;    versions of the Macro Assembler, nor in competitive
  48. ;    products.
  49. ;
  50. ;---------------------------------------------------------------
  51.  
  52. ;---------------------------------------------------------------
  53. ; Compiler directives
  54. ;---------------------------------------------------------------
  55.     Title    LOADALL_386
  56.     .radix    16
  57.     .8086
  58.  
  59.  
  60. ;---------------------------------------------------------------
  61. ; Interrupt vector segment
  62. ;---------------------------------------------------------------
  63. ABS0    segment at 0
  64.     org 6*4
  65.     INT_6        dd    ?
  66. ABS0    ends
  67.  
  68.  
  69. ;---------------------------------------------------------------
  70. ; Structure definitions
  71. ;---------------------------------------------------------------
  72. Desc_cache    STRUC
  73.         db    0
  74.     _Type    db    ?
  75.     _CS32    db    0
  76.         db    0
  77.     _Addr    dd    ?
  78.     _Limit    dd    ?
  79. Desc_cache    ENDS
  80.  
  81.  
  82. Loadall_struc    STRUC
  83.     _Cr0        dd    0
  84.     _Eflags     dd    2
  85.     _Eip        dd    0
  86.     _Edi        dd    66666666h
  87.     _Esi        dd    77777777h
  88.     _Ebp        dd    55555555h
  89.     _Esp        dd    88888888h
  90.     _Ebx        dd    22222222h
  91.     _Edx        dd    44444444h
  92.     _Ecx        dd    33333333h
  93.     _Eax        dd    11111111h
  94.     _Dr6        dd    0
  95.     _Dr7        dd    0
  96.     _Tr        dd    0
  97.     _Ldt        dd    0
  98.     _Gs        dd    5555h
  99.     _Fs        dd    4444h
  100.     _Ds        dd    2222h
  101.     _Ss        dd    6666h
  102.     _Cs        dd    1111h
  103.     _Es        dd    3333h
  104.     TSS_Desc    dd    00008900h,00070000h,00000800h
  105.     IDT_Desc    dd    00000000h,00000000h,000003ffh
  106.     Gdt_Desc    dd    00000000h,00000000h,00000000h
  107.     Ldt_Desc    dd    00008200h,00090000h,00000088h
  108.     GS_Desc     dd    00009300h,00050000h,0000ffffh
  109.     FS_Desc     dd    00009300h,00040000h,0000ffffh
  110.     DS_Desc     dd    00009300h,00020000h,0000ffffh
  111.     SS_Desc     dd    00009300h,00060000h,0000ffffh
  112.     CS_Desc     dd    00009b00h,00000000h,0000ffffh
  113.     ES_Desc     dd    00009300h,00030000h,00fffffch
  114. Loadall_Struc    ENDS
  115.  
  116.  
  117. Descriptor  STRUC
  118.     Seg_limit        dw        ?        ; Segment limit
  119.     Base_A15_A00    dw        ?        ; A00..A15 of base address
  120.     Base_A23_A16    db        ?        ; A16..A23 of base address
  121.     Access_rights   db        ?        ; Segment access rights
  122.     Limit_A19_A16   db        ?        ; Granularity, Op-size,
  123.                     ;  Limit A16..A19
  124.     Base_A31_A24    db        ?        ; A24..A31 of base address
  125. Descriptor  ENDS
  126.  
  127.  
  128. INT_Desc    STRUC
  129.     IGate_Offset    dw        ?        ; Offset of handler
  130.     CSEG_Sel        dw        ?        ; Code segment selector
  131.             db        0
  132.             db        86h     ; 286 interrupt gate=16bit
  133.                     ;  CS:IP, FLAGS
  134.     Resvd        dw        0        ; Reserved=0
  135. INT_Desc    ENDS
  136.  
  137.  
  138. ;-----------------------------------------------------------------------------
  139. ; Macro definitions
  140. ;-----------------------------------------------------------------------------
  141.     Init_descriptor    macro   segment,offset,desc_name
  142.     push    ax
  143.     push    dx
  144.     push    si
  145.     push    es
  146.     mov    ax,&segment        ;; get segment name
  147.     mov    es,ax            ;;   to form 24 bit address
  148.     mov    si,&offset        ;;
  149.     mov    ax,es            ; point to control block
  150.     xor    dh,dh            ; clear upper register
  151.     mov    dl,ah            ; build high byte of 32-bit address
  152.     shr    dl,4            ; use only high nibble from (AX)
  153.     shl    ax,4            ; strip high nibble from segment
  154.     add    ax,si            ; add the GDT offset to develop low word
  155.     adc    dx,0            ; adjust high byte if carry from low
  156.     mov    &desc_name.Base_A15_A00,ax    ;; low word of address
  157.     mov    &desc_name.Base_A23_A16,dl    ;; high byte of address
  158.     mov    &desc_name.Base_A31_A24,dh    ;; high byte of linear address
  159.     pop    es
  160.     pop    si
  161.     pop    dx
  162.     pop    ax
  163.     endm
  164.  
  165.  
  166. FARJMP    MACRO    destination,selector    ; dynamic JMP FAR SEG:OFF
  167.     db    0eah            ;; jmp instruction
  168.     dw    offset destination    ;; offset word
  169.     dw    selector        ;; segment selector word
  170.     endm
  171.  
  172.  
  173. LONGJMP MACRO    destination,selector    ; dynamic JMP FAR SEG:OFF
  174.     db    0eah            ;; jmp instruction
  175.     dd    offset destination    ;; offset word
  176.     dw    selector        ;; segment selector word
  177.     endm
  178.  
  179.  
  180. IO_DELAY    MACRO
  181.     out    0edh,ax
  182.     endm
  183.  
  184. LOADALL     MACRO
  185.     db    0fh,07h
  186.     ENDM
  187.  
  188.  
  189. PRINT_STRING    MACRO    MSG_NAME
  190.     mov    ah,9
  191.     mov    dx,offset MSG_NAME
  192.     int    21h
  193.     ENDM
  194.  
  195.  
  196.     _DATA     SEGMENT PARA PUBLIC 'DATA'
  197. ;---------------------------------------------------------------
  198. ; Equates & local variables
  199. ;---------------------------------------------------------------
  200. ; Protected mode access rights
  201. ;---------------------------------------------------------------
  202.     CS_access    equ    10011011b
  203.     DS_access    equ    10010011b
  204.  
  205. ;---------------------------------------------------------------
  206. ; Text equates
  207. ;---------------------------------------------------------------
  208.     CRLF        equ    <0dh,0ah>
  209.     CRLF$        equ    <CRLF,'$'>
  210.     INT6        equ    [bp-4]
  211.  
  212. ;---------------------------------------------------------------
  213. ; Loadall table(s)
  214. ;---------------------------------------------------------------
  215.     Loadall_tbl    Loadall_struc <>
  216.     Machine_State    Loadall_struc <>
  217.  
  218. ;---------------------------------------------------------------
  219. ; Global Descriptor Table
  220. ;---------------------------------------------------------------
  221.     GDT_386 Descriptor    <Gdt3_len-1,,,DS_access>
  222.     CSEG3    Descriptor    <0ffffh,0,0,CS_access>
  223.     DSEG3    Descriptor    <0ffffh,0,20h,DS_access>
  224.     Gdt3_len      equ    $-Gdt_386
  225.  
  226. ;---------------------------------------------------------------
  227. ; Interrupt Descriptor Table
  228. ;---------------------------------------------------------------
  229. IDT_386 INT_Desc    <Offset INT13,CSEG3-GDT_386>    ; INT00
  230.     INT_Desc    <Offset INT01,CSEG3-GDT_386>    ; INT01
  231.     INT_Desc    <Offset INT13,CSEG3-GDT_386>    ; INT02
  232.     INT_Desc    <Offset INT13,CSEG3-GDT_386>    ; INT03
  233.     INT_Desc    <Offset INT13,CSEG3-GDT_386>    ; INT04
  234.     INT_Desc    <Offset INT13,CSEG3-GDT_386>    ; INT05
  235.     INT_Desc    <Offset INT13,CSEG3-GDT_386>    ; INT06
  236.     INT_Desc    <Offset INT13,CSEG3-GDT_386>    ; INT07
  237.     INT_Desc    <Offset INT13,CSEG3-GDT_386>    ; INT08
  238.     INT_Desc    <Offset INT13,CSEG3-GDT_386>    ; INT09
  239.     INT_Desc    <Offset INT13,CSEG3-GDT_386>    ; INT0a
  240.     INT_Desc    <Offset INT13,CSEG3-GDT_386>    ; INT0b
  241.     INT_Desc    <Offset INT13,CSEG3-GDT_386>    ; INT0c
  242.     INT_Desc    <Offset INT13,CSEG3-GDT_386>    ; INT0d
  243. IDT3_Len    equ    $-IDT_386
  244.  
  245. ;---------------------------------------------------------------
  246. ; Misc. local variables
  247. ;---------------------------------------------------------------
  248.     Mem_buffer    db    400h dup (0)    ; Store 2M mem.
  249.     Buffer        db    40h dup (0)
  250.     Buffer2     dw    10h dup (0)
  251.  
  252.     RM_IDT3_Ptr    dw    (256d*4)-1    ; Real-mode IDT
  253.             dd    0        ;  pointer
  254.             dw    0
  255.  
  256.  
  257. ;---------------------------------------------------------------
  258. ; String Messages
  259. ;---------------------------------------------------------------
  260. Passed    db    "    PASSED.",CRLF$
  261. Failed    db    "--> FAILED <--",CRLF$
  262. Not_386 db    "Not 80386 class computer.",CRLF$
  263. Rmvd    db    "LOADALL removed from 80386 mask.",CRLF$
  264. RFail    db    "Registers weren't loaded correctly."
  265. LF    db     CRLF$
  266.  
  267. ;---------------------------------------------------------------
  268. ; I'm doing this wierd string definition technique to limit the
  269. ; page width to 64 characters.
  270. ;---------------------------------------------------------------
  271. Test_1    label    word
  272. db    "Test 1:  Testing 386 LOADALL instruction:         ",24
  273.  
  274. Test_2    label    word
  275. db    "Test 2:  Testing extended memory in real mode:    ",24
  276.  
  277. Test_3    label    word
  278. db    "Test 3:  Testing Present BIT in descriptor:       ",24
  279.  
  280. Test_4    label    word
  281. db    "Test 4:  Testing 32-bit protected mode:           ",24
  282.  
  283. Test_5    label    word
  284. db    "Test 5:  Testing 32-bit real mode:                ",24
  285.  
  286. Test_6    label    word
  287. db    "Test 6:  Testing Granularity BIT:                 ",24
  288.  
  289. Test_7    label    word
  290. db    "Test 7:  Testing Execution breakpoints:           ",24
  291.  
  292. Test_8    label    word
  293. db    "Test 8:  Testing byte, write, data breakpoints:   ",24
  294.  
  295. _DATA    ENDS
  296.  
  297.  
  298.     _TEXT    SEGMENT PARA PUBLIC 'CODE'
  299.     ASSUME    CS:_TEXT, ds:_DATA, ES:_DATA, SS:STACK
  300.     .386P
  301. ;---------------------------------------------------------------
  302. ; A little CS-relative data for the stack pointer.  This is
  303. ; to avoid using other kludge techniques, caused by using
  304. ; LOADALL, that make using the data segment undesirable.
  305. ;---------------------------------------------------------------
  306.     Stack_ptr    dd    0
  307.             dw    0
  308.  
  309. ;---------------------------------------------------------------
  310.   LOADALL_386    proc    far
  311. ;---------------------------------------------------------------
  312.     PUSH    DS            ; Setup the stack to
  313.     XOR    AX,AX            ;  return to DOS
  314.     PUSH    AX
  315.  
  316.     MOV    AX,_Data
  317.     MOV    DS,AX
  318.     MOV    ES,AX
  319.  
  320. ;---------------------------------------------------------------
  321. ; Check CPU type
  322. ;---------------------------------------------------------------
  323.     Call    CPU_Type        ; 386, 486?
  324.     cmp    ax,3            ; 386?
  325.     je    short @F        ; yep
  326.     Print_String    LF
  327.     Print_String    Not_386
  328.     retf                ; go split
  329.  
  330. @@:    enter    4,0            ; create stack frame
  331.     mov    word ptr INT6,offset INT6_handler
  332.     mov    INT6+2,cs
  333.     call    set_INT6_vector     ; set our INT6 handler
  334.     cli
  335.     Call    Save_State
  336.     Print_String    LF
  337.     Print_String    Test_1
  338.     Init_descriptor <seg Gdt_386>,<offset Gdt_386>,Gdt_386
  339.     Init_descriptor cs,   0,CSEG3
  340.  
  341. ;---------------------------------------------------------------
  342. ;
  343. ; TEST1:  16-bit Real mode
  344. ;      Test general purpose registers
  345. ;      Test Segment registers
  346. ;      Test Descriptor cache base address
  347. ;
  348. ;  (1) Setup LOADALL structures, and pointers
  349. ;  (2) Execute LOADALL
  350. ;  (3) Verify results of the test
  351. ;
  352. ;---------------------------------------------------------------
  353.     mov    eax,cs            ; Prepare a 32-bit
  354.     shl    eax,4            ;  physical address that
  355.                     ;  is put in the LOADALL
  356.                     ;  CS descriptor cache.
  357.     mov    Loadall_tbl.CS_Desc._Addr,eax
  358.  
  359.     mov    eax,cr0         ; Initialize CR0 in the
  360.     and    eax,0fffffff0h        ;  LOADALL data table
  361.     mov    Loadall_tbl._CR0,eax    ;  DR6, DR7, EIP
  362.     mov    eax,dr6
  363.     mov    ebx,dr7
  364.     mov    Loadall_tbl._DR6,eax
  365.     mov    Loadall_tbl._DR7,ebx
  366.     mov    Loadall_tbl._EIP,offset Verify_State
  367.     mov    dword ptr cs:stack_ptr,esp      ; save SS:ESP
  368.     mov    word ptr cs:stack_ptr[4],ss
  369.     mov    edi,offset loadall_tbl
  370.     LOADALL
  371.     nop                ; If LOADALL is removed
  372.     Print_String    failed        ;  from the CPU mask,
  373.     Print_String    Rmvd        ;  then fall through
  374.                     ;  to here.
  375. Loadall_RET:
  376.     call    Restore_state
  377.     call    set_int6_vector
  378.     leave
  379.     retf
  380.  
  381. ;---------------------------------------------------------------
  382.   Verify_State:         ; Verify that LOADALL worked
  383. ;---------------------------------------------------------------
  384. ; This is where we land for the first test of '386 LOADALL.
  385. ; The purpose of this test is to verify that all the general
  386. ; purpose registers get loaded correctly.  Specifically, we are
  387. ; testing to verify that all segment registers contain values
  388. ; that don't correspond to the memory addresses they appear to
  389. ; be pointing to.  In other words, we are checking that the
  390. ; that the segment registers have one value, while their
  391. ; associated hidden descriptor cache registers have different
  392. ; values.
  393. ;---------------------------------------------------------------
  394.     cmp    eax,11111111h        ; Test EAX
  395.     jne    @F
  396.     cmp    ebx,22222222h        ; Test EBX
  397.     jne    @F
  398.     cmp    ecx,33333333h        ; Test ECX
  399.     jne    @F
  400.     cmp    edx,44444444h        ; Test EDX
  401.     jne    @F
  402.     cmp    ebp,55555555h        ; Test EBP
  403.     jne    @F
  404.     cmp    edi,66666666h        ; Test EDI
  405.     jne    @F
  406.     cmp    esi,77777777h        ; Test ESI
  407.     jne    @F
  408.     cmp    esp,88888888h        ; Test ESP
  409.     jne    short @F
  410.     mov    ax,cs            ; Test CS
  411.     cmp    ax,1111h
  412.     jne    short @F
  413.     mov    ax,ds            ; Test DS
  414.     cmp    ax,2222h
  415.     jne    short @F
  416.     mov    ax,es            ; Test ES
  417.     cmp    ax,3333h
  418.     jne    short @F
  419.     mov    ax,fs            ; Test FS
  420.     cmp    ax,4444h
  421.     jne    short @F
  422.     mov    ax,gs            ; Test GS
  423.     cmp    ax,5555h
  424.     jne    short @F
  425.     mov    ax,ss            ; Test SS
  426.     cmp    ax,6666h
  427.     jne    short @F
  428.     cmp    dword ptr ds:[0],02020202h ; Test DS Desc Cache
  429.     jne    short @F
  430.     cmp    dword ptr es:[0],03030303h ; Test ES Desc Cache
  431.     jne    short @F
  432.     cmp    dword ptr fs:[0],04040404h ; Test FS Desc Cache
  433.     jne    short @F
  434.     cmp    dword ptr gs:[0],05050505h ; Test GS Desc Cache
  435.     jne    short @F
  436.     cmp    dword ptr ss:[0],06060606h ; Test SS Desc Cache
  437.     jne    short @F
  438.     mov    ax,_Data        ; Reset segment regs.
  439.     mov    ds,ax
  440.     mov    es,ax
  441.     lss    esp,fword ptr cs:stack_ptr    ; Reset SS:ESP
  442.     FARJMP    <Loadall_test>,<seg _Text>    ; Continue
  443.  
  444. ;---------------------------------------------------------------
  445. ; Loadall failed the REGISTERs test.
  446. ;---------------------------------------------------------------
  447. @@:    mov    ax,_Data
  448.     mov    ds,ax
  449.     mov    es,ax
  450.     lss    esp,fword ptr cs:stack_ptr
  451.     FARJMP    <@F>,<seg _Text>
  452. @@:    Print_String    failed
  453.     Print_String    RFail
  454.     jmp    loadall_ret
  455.  
  456. ;---------------------------------------------------------------
  457. ; LOADALL passed
  458. ;---------------------------------------------------------------
  459. Loadall_test:
  460.     Print_String    passed
  461.  
  462. ;---------------------------------------------------------------
  463. ;
  464. ; TEST2:  Access extended memory while in real mode (@ 2M).
  465. ;
  466. ;  (1) Fill in LOADALL structure with "reasonable" values
  467. ;  (2) Save contents of extended memory
  468. ;  (3) Write data pattern in extended memory
  469. ;  (4) Set LOADALL registers used by this test
  470. ;  (5) LOADALL
  471. ;  (6) Verify results
  472. ;  (7) Restore original data in extended memory
  473. ;
  474. ;---------------------------------------------------------------
  475. ; In this test, I'll access extended memory while in real mode.
  476. ; I'll assume the computer has at least 2M of memory.  By
  477. ; assuming 2M, I don't need to enable A20 on the CPU bus, since
  478. ; memory @ 2M doesn't assert A20.
  479. ;---------------------------------------------------------------
  480. ; Fill LOADALL structure with more reasonable values.
  481. ;---------------------------------------------------------------
  482.     mov    Loadall_tbl._EAX,0
  483.     mov    Loadall_tbl._EBX,0
  484.     mov    Loadall_tbl._ECX,0
  485.     mov    Loadall_tbl._EDX,0
  486.     mov    Loadall_tbl._EBP,0
  487.     mov    Loadall_tbl._ESP,esp
  488.     mov    Loadall_tbl._CS,cs
  489.     mov    Loadall_tbl._DS,ds
  490.     mov    Loadall_tbl._ES,es
  491.     mov    Loadall_tbl._FS,8000h
  492.     mov    Loadall_tbl._GS,8000h
  493.     mov    Loadall_tbl._SS,ss
  494.  
  495. ;---------------------------------------------------------------
  496. ; Load segment descriptor cache registers:
  497. ;  DS=ES = _DATA segment
  498. ;  FS=GS = 80000h (8000:0)
  499. ;  SS     = STACK segment
  500. ;---------------------------------------------------------------
  501.     mov    ax,ds
  502.     movzx    eax,ax
  503.     shl    eax,4
  504.     mov    bx,ss
  505.     movzx    ebx,bx
  506.     shl    ebx,4
  507.     mov    Loadall_tbl.DS_Desc._addr,eax
  508.     mov    Loadall_tbl.ES_Desc._addr,eax
  509.     mov    Loadall_tbl.FS_Desc._addr,80000h;
  510.     mov    Loadall_tbl.GS_Desc._addr,80000h
  511.     mov    Loadall_tbl.SS_Desc._addr,ebx
  512.  
  513. ;---------------------------------------------------------------
  514. ; Slip into protected mode to save the contents of memory @ 2M,
  515. ; and write a test pattern into that memory.
  516. ;---------------------------------------------------------------
  517.     Print_String    Test_2
  518.     lgdt    fword ptr Gdt_386    ; Load the GDT
  519.     mov    ebx,cr0         ; enter protected mode
  520.     or    bl,1
  521.     mov    cr0,ebx
  522.     FARJMP    <@F>,<CSEG3-Gdt_386>
  523.  
  524. @@:    mov    dx,DSEG3-Gdt_386    ; Get segment selector
  525.     mov    ds,dx            ;  for DS @ 2M
  526.     mov    cx,400h / 4
  527.     mov    si,0
  528.     mov    di,offset Mem_buffer
  529.     rep    movsd            ; Save memory
  530.     mov    eax,5aa5aa5ah        ; Test pattern
  531.     mov    cx,400h / 4
  532.     mov    di,0
  533.     mov    es,dx            ; ES = 2M
  534.     rep    stosd            ; Store test pattern
  535.     and    bl,not 1        ; exit protected mdoe
  536.     mov    cr0,ebx
  537.     FARJMP    <@F>,<_TEXT>
  538.  
  539. ;---------------------------------------------------------------
  540. ; Set LOADALL-image registers used by this test
  541. ;---------------------------------------------------------------
  542. @@:    mov    ax,_data
  543.     mov    ds,ax
  544.     mov    es,ax
  545.     mov    Loadall_tbl._EAX,5aa5aa5ah    ; Test pattern
  546.     mov    Loadall_tbl._ECX,400h / 4    ; # of DWORDS
  547.     mov    Loadall_tbl._ESI,offset Mem_buffer
  548.     mov    Loadall_tbl._EDI,0h        ; ES:0
  549.     mov    Loadall_tbl._EIP,offset @F    ; EIP
  550.     mov    Loadall_tbl.ES_Desc._Addr,200000h    ; 2M
  551.     mov    edi,offset loadall_tbl
  552.     LOADALL
  553.  
  554. ;---------------------------------------------------------------
  555. ; Check memory for a match of the pattern
  556. ;---------------------------------------------------------------
  557. @@:    repz    scasd            ; data match?
  558.     mov    bx,_Data        ; ES still points to 2M,
  559.     mov    ds,bx            ;  so I can reset DS and
  560.     mov    cx,400h / 4        ;  restore the original
  561.     mov    di,0            ;  contents @ 2M without
  562.     rep    movsd            ;  changing ES.
  563.     mov    es,bx            ; Set ES to real mode
  564.     lss    esp,fword ptr cs:stack_ptr    ; Restore SS:ESP
  565.     FARJMP    <@F>,<_TEXT>        ; Must jump to R/W CS
  566. @@:    jz    short @Test2_Pass
  567.  
  568.     PRINT_STRING    failed
  569.     jmp    short @Test3
  570.  
  571. @Test2_Pass:
  572.     PRINT_STRING    passed
  573.  
  574. ;---------------------------------------------------------------
  575. ;
  576. ; TEST3:  Test that the Present bit gets loaded w/out exception,
  577. ;      but when a segment is accessed INT13 get generated.
  578. ;
  579. ;  (1) Load GDT & IDT pointers into LOADALL table
  580. ;  (2) Set PM bit, CS selector, EIP offset, clear P bit
  581. ;  (3) LOADALL
  582. ;  (4) Verify Results
  583. ;
  584. ;-----------------------------------------------------------------------------
  585. @Test3: Print_String    Test_3
  586.  
  587. ;---------------------------------------------------------------
  588. ; Initialize the GDT & IDT descriptor cache
  589. ;---------------------------------------------------------------
  590.     mov    eax,Loadall_tbl.DS_Desc._Addr
  591.     mov    ebx,eax
  592.     mov    Loadall_tbl.ES_Desc._Addr,eax
  593.     add    eax,offset Gdt_386
  594.     add    ebx,offset Idt_386
  595.     mov    Loadall_tbl.GDT_Desc._Addr,eax
  596.     mov    Loadall_tbl.GDT_Desc._Limit,Gdt3_len-1
  597.     mov    Loadall_tbl.Idt_Desc._Addr,ebx
  598.     mov    Loadall_tbl.Idt_Desc._Limit,Idt3_len-1
  599.  
  600.     or    Loadall_tbl._CR0,1        ; set PM bit
  601.     mov    Loadall_tbl._ESI,0
  602.     mov    Loadall_tbl._CS,CSEG3-Gdt_386    ; CS selector
  603.     mov    Loadall_tbl._EIP,offset @Test_Present
  604.     and    Loadall_tbl.GS_Desc._Type,7fh    ; clear Present
  605.     mov    edi,offset loadall_tbl        ;  bit in GS
  606.     LOADALL
  607.  
  608. @Test_Present:
  609.     mov    si,gs:[si][2]        ; choose this because
  610.                     ;  it's a 4-byte instr.
  611.     Lidt    fword ptr RM_IDT3_Ptr    ; Restore real-mode IDT
  612.     mov    eax,cr0         ; Exit protected mode.
  613.     and    al,not 1
  614.     mov    cr0,eax
  615.     FARJMP    <@F>,<_TEXT>        ; Return to R/W, real-
  616.                     ;  mode code segment
  617.  
  618. @@:    test    si,1            ; pass test?
  619.     jnz    short @F        ; yep
  620.     Print_String    failed
  621.     jmp    short @Test4
  622.  
  623. @@:    Print_String    passed
  624.  
  625. ;---------------------------------------------------------------
  626. ;
  627. ; TEST4:  Test 32-bit Protected Mode operation
  628. ;
  629. ;  (1) Set LOADALL operand size, PM bits, and EIP offset
  630. ;  (2) LOADALL
  631. ;  (3) Verify Results
  632. ;
  633. ;---------------------------------------------------------------
  634. @Test4: Print_String    Test_4
  635.  
  636. ;---------------------------------------------------------------
  637. ; Perform 32-bit protected mode test
  638. ;---------------------------------------------------------------
  639.     or    Loadall_tbl.CS_Desc._CS32,40h    ; CS32 bit
  640.     mov    Loadall_tbl._EDI,offset Loadall_tbl
  641.     mov    Loadall_tbl._EIP,offset PM32
  642.     LOADALL
  643.  
  644. ;---------------------------------------------------------------
  645. ; This test uses a simple technique to determine if we are in
  646. ; 32-bit mode or 16-bit mode:
  647. ;
  648. ; In 16-bit mode, this code will be executed as:
  649. ;    mov    si,1234h
  650. ;    nop
  651. ;    nop
  652. ;
  653. ; In 32-bit mode, this code will be executed as:
  654. ;    mov    esi,90901234h    ; The two NOP's are absorbed
  655. ;                ;  into the 32-bit operand.
  656. ;
  657. ;---------------------------------------------------------------
  658. ;---------------------------------------------------------------
  659. ; In 16-bit mode, this code will be executed as:
  660. ;    mov    di,1234h
  661. ;    nop
  662. ;    nop
  663. ;
  664. ; In 32-bit mode, this code will be executed as:
  665. ;    mov    edi,90901234h
  666. ;---------------------------------------------------------------
  667. PM32:    mov    si,1234h
  668.     nop
  669.     nop
  670.  
  671. ;---------------------------------------------------------------
  672. ; Now, we need to exit 32-bit mode gracefully.    In order to do
  673. ; that, we need code that will generate predictable results in
  674. ; both 32-bit, and 16-bit mode.  If we are in 32-bit mode, then
  675. ; the following compiled code will behave as documented under
  676. ; the '32-bit mode' column.  If we failed to enter 32-bit mode,
  677. ; then the following compiled code will behave as documented
  678. ; under the '16-bit mode' column.  In order to exit gracefully,
  679. ; we need to know which mode we are in!  Hence the following
  680. ; code to detect it!:
  681. ;
  682. ; 16-bit mode         32-bit mode
  683. ; push      ax         push    eax
  684. ; mov      ax,si      mov     eax,esi
  685. ; shr      ax,10h     shr     eax,10h ; AX=9090 if in 32-bit
  686. ;                     ; AX=0    if in 16-bit
  687. ;
  688. ; cmp      al,90h     cmp     al,90h  ; PASS=32-bit, FAIL=16-bit
  689. ; pushf          pushf         ; save results for later
  690. ; shl      ax,10h     shl     eax,10h ; EAX=90900000 if in 32-bit
  691. ; mov      si,ax      mov     esi,eax ; ESI=90900000 if in 32-bit
  692. ;                     ; ESI=66660000 if in 16-bit
  693. ; popf             popf         ; restore ZF
  694. ; pop      ax         pop     eax
  695. ;
  696. ; So, the result of this code is to exit 32-bit mode if we got
  697. ; there, and to keep going in 16-bit mode if we didn't.
  698. ;---------------------------------------------------------------
  699.     push    ax            ; See the above
  700.     mov    ax,si            ;  explanation on how
  701.     shr    ax,10h            ;  this code works
  702.     cmp    al,90h
  703.     pushf
  704.     shl    ax,10h
  705.     mov    si,ax
  706.     popf
  707.     pop    ax
  708.     jne    short @No_PM32bitCS
  709.     or    si,1            ; set SI if 32-bit mode
  710.  
  711. ;---------------------------------------------------------------
  712. ; 32-bit JUMP instruction, to transfer control back to a 16-bit
  713. ; segment
  714. ;---------------------------------------------------------------
  715.     LONGJMP <@F>,<CSEG3-GDT_386>    ; Construct 32-bit far
  716.                     ; JMP
  717.  
  718. @No_PM32bitCS:                ; FAR JUMP if stuck in
  719.     FARJMP    <@F>,<CSEG3-GDT_386>    ;  16-bit mode.
  720.  
  721. @@:    Lidt    fword ptr RM_IDT3_Ptr    ; Restore real-mode IDT
  722.     mov    eax,cr0         ; Exit protected mode.
  723.     and    al,not 1
  724.     mov    cr0,eax
  725.     FARJMP    <@F>,<_TEXT>        ; Jump to real-mode
  726.                     ;  code segment
  727. @@:    mov    ax,_Data        ; Restore real-mode
  728.     mov    ds,ax            ;  segment registers
  729.     mov    es,ax
  730.     test    si,1            ; 32-bit mode passed?
  731.     jnz    short @F        ; yep
  732.     Print_String    failed
  733.     jmp    short @Test5
  734.  
  735. @@:    Print_String    passed
  736.  
  737. ;---------------------------------------------------------------
  738. ;
  739. ; TEST5:  Test 32-bit real-mode operation
  740. ;
  741. ;  (1) Clear operand size, PM bits, and set EIP offset
  742. ;  (2) LOADALL
  743. ;  (3) Verify Results
  744. ;  (4) Get the h&*@! out of 32-bit real-mode
  745. ;
  746. ;---------------------------------------------------------------
  747. ; Test 32-bit real-mode operation.  Make sure we can put the
  748. ; processor in an illegal state:  32-bit real-mode.
  749. ;---------------------------------------------------------------
  750. @Test5: Print_String    Test_5
  751.     and    Loadall_tbl._CR0,not 1        ; disable PM bit
  752.     and    Loadall_tbl.CS_Desc._Type,not 8 ; make CS R/W
  753.                         ;  Data segment
  754.     mov    Loadall_tbl._EIP,offset RM32    ; Load EIP
  755.     LOADALL
  756.  
  757. ;---------------------------------------------------------------
  758. ; This test uses the exact same technique documented in TEST4.
  759. ; See TEST4 for an explanation of these next two code sections.
  760. ;---------------------------------------------------------------
  761. RM32:    mov    si,1234h
  762.     nop
  763.     nop
  764.  
  765. ;---------------------------------------------------------------
  766. ; See TEST4 for an explanation of this code section.
  767. ;---------------------------------------------------------------
  768.     push    ax            ; See the above
  769.     mov    ax,si            ;  explanation on how
  770.     shr    ax,10h            ;  this code works
  771.     cmp    al,90h
  772.     pushf
  773.     shl    ax,10h
  774.     mov    si,ax
  775.     popf
  776.     pop    ax
  777.  
  778. ;---------------------------------------------------------------
  779. ; Now getting out of 32-bit real mode is a bit more complicated
  780. ; than you may think.  According to Intel, the internal
  781. ; descriptor cache registers get re-loaded with default values
  782. ; each time the segment is loaded.  But the operand size bit in
  783. ; the CS descriptor cache doesn't get cleared in a long jump.
  784. ; So, to program around this, I need to either execute LOADALL
  785. ; again, or go to protected mode, jump to a 16-bit code segment,
  786. ; then go back to real mode.  I think I will do the latter.
  787. ;---------------------------------------------------------------
  788.     jne    short @RM32_Fail    ; Do something else
  789.     mov    eax,cr0         ; Enter protected mode
  790.     or    al,1
  791.     mov    cr0,eax
  792.     LONGJMP <@F>,<CSEG3-GDT_386>    ; To 16-bit CS
  793.  
  794. @@:    Lidt    fword ptr RM_IDT3_Ptr    ; Reload real-mode IDT
  795.     and    al,not 1        ; Exit protected mode
  796.     mov    cr0,eax
  797.     FARJMP    <@RM32_Pass>,<seg _text>; Back to real-mode CS
  798.  
  799. @RM32_Fail:
  800.     Print_String    failed
  801.     jmp    short @Test6
  802.  
  803. @RM32_Pass:
  804.     mov    ax,_Data        ; Reload real-mode
  805.     mov    ds,ax            ;  segment registers
  806.     mov    es,ax
  807.     Print_String    passed
  808.  
  809. ;---------------------------------------------------------------
  810. ;
  811. ; TEST6:  Test Granularity bit.  Test that the granularity bit
  812. ;      in the descriptor cache has no effect on the limit
  813. ;      field of the descriptor cache.  This is a three-part
  814. ;      test.  First, by setting G=1 in a segment descriptor
  815. ;      cache whose limit=64k should cause an exception.
  816. ;      Second, ES_LIMIT=16M-4.  This LIMIT can't ever be
  817. ;      generated under program control.  So we simply need
  818. ;      to access memory @ 16M-8 to verify this test.  If
  819. ;      an exception gets generated, then the test failed.
  820. ;      Third, try to access memory @ 16M-4.    If an exception
  821. ;      ISN'T generated, then the test failed.
  822. ;
  823. ;  (1) Set Present, Granularity bits, and EIP offset
  824. ;  (2) LOADALL
  825. ;  (3) Verify results
  826. ;
  827. ;---------------------------------------------------------------
  828. ; Test Granularity bit:  Test that G=1 has no effect in the
  829. ; descriptor cache register.  In the GS descriptor cache, I set
  830. ; the limit=64k.  If G=1 has any effect on this field, then the
  831. ; following memory access will pass.  We want it to fail, and
  832. ; generate an exception-13.
  833. ;---------------------------------------------------------------
  834. @Test6: Print_String    Test_6
  835.     or    Loadall_tbl._CR0,1        ; set PM bit
  836.     or    Loadall_tbl.GS_Desc._Type,80h    ; set P=1
  837.     or    Loadall_tbl.GS_Desc._CS32,80h    ; set G=1
  838.     and    Loadall_tbl.CS_Desc._CS32,0bfh    ; clear CS32 bit
  839.     mov    Loadall_tbl._EIP,offset @Test_Gran
  840.     LOADALL
  841.  
  842. @Test_Gran:
  843.     mov    esi,10000h        ; should generate exc.
  844.     mov    si,gs:[esi]
  845.     shl    si,1            ; save results
  846.     mov    esi,0fffff8h        ; 16M-8
  847.     mov    si,es:[esi]        ; shouldn't generate exc
  848.     shl    si,1
  849.     mov    esi,0fffffch        ; 16M-4
  850.     mov    si,es:[esi]        ; should generate exc.
  851.     add    esi,4
  852.     Lidt    fword ptr RM_IDT3_Ptr    ; Restore real-mode IDT
  853.     mov    eax,cr0
  854.     and    al,not 1
  855.     mov    cr0,eax
  856.     FARJMP    <@F>,<_TEXT>
  857.  
  858. @@:    and    si,7
  859.     cmp    si,5            ; pass test?
  860.     jnz    short @F        ; yep
  861.     Print_String    failed
  862.     jmp    short @Test7
  863.  
  864. @@:    Print_String    passed
  865.  
  866. ;---------------------------------------------------------------
  867. ; The following two expamples show how to use the debug
  868. ; registers to generate execution and data break points.  They
  869. ; are included in this program because they use LOADALL to set
  870. ; DR7.    Forgive the fact that they are poorly documented.
  871. ;---------------------------------------------------------------
  872. ;
  873. ; TEST7:  Test execution breakpoints through debug registers.
  874. ;
  875. ;  (1) Clear granularity bit, set ES_LIMIT=64k, set EIP offset
  876. ;  (2) Set breakpoint qualifiers
  877. ;  (3) LOADALL
  878. ;  (4) Generate execution breakpoints
  879. ;  (5) Verify results
  880. ;
  881. ;---------------------------------------------------------------
  882. @Test7: Print_String    Test_7
  883.     and    Loadall_tbl.GS_Desc._CS32,7fh    ; set G=0
  884.     mov    Loadall_tbl.ES_Desc._Limit,0ffffh; limit=64k
  885.     mov    Loadall_tbl._EIP,offset Test_DR0
  886.  
  887. ;---------------------------------------------------------------
  888. ; Set a series of execution break points in the debug registers.
  889. ;---------------------------------------------------------------
  890.     mov    bx,cs
  891.     movzx    ebx,bx
  892.     shl    ebx,4
  893.     lea    eax,[ebx][dword ptr Test_Dr0]
  894.     mov    dr0,eax
  895.     lea    eax,[ebx][dword ptr Test_DR1]
  896.     mov    dr1,eax
  897.     lea    eax,[ebx][dword ptr Test_DR2]
  898.     mov    dr2,eax
  899.     lea    eax,[ebx][dword ptr Test_DR3]
  900.     mov    dr3,eax
  901.     mov    Loadall_tbl._DR7,0aah    ; enable all code
  902.                     ;  breakpoints
  903.     LOADALL
  904.  
  905. Test_DR0:
  906.     nop
  907. Test_DR1:
  908.     nop
  909. Test_DR2:
  910.     nop
  911. Test_DR3:
  912.     nop
  913.  
  914.     Lidt    fword ptr RM_IDT3_Ptr    ; Restore real-mode IDT
  915.     mov    eax,cr0         ; exit protected mode
  916.     and    al,not 1
  917.     mov    cr0,eax
  918.     FARJMP    <@F>,<seg _text>
  919.  
  920. @@:    and    si,0fh
  921.     cmp    si,0fh            ; pass all breakpoints?
  922.     je    short @F        ; yep
  923.     Print_String    failed
  924.     jmp    @Test8
  925.  
  926. @@:    Print_String    passed
  927.  
  928. ;---------------------------------------------------------------
  929. ;
  930. ; TEST8:  Test byte-size data write breakpoints
  931. ;
  932. ;  (1) Set EIP offset
  933. ;  (2) Set breakpoint qualifiers
  934. ;  (3) LOADALL
  935. ;  (4) Generate data breakpoints
  936. ;  (5) Verify results
  937. ;
  938. ;---------------------------------------------------------------
  939. @Test8: Print_String    Test_8
  940.     mov    Loadall_tbl._EAX,55h
  941.     mov    Loadall_tbl._ECX,40h
  942.     mov    Loadall_tbl._EDI,offset Buffer
  943.     mov    Loadall_tbl._EIP,offset @Test_DRBW
  944.  
  945.     mov    bx,ds
  946.     movzx    ebx,bx
  947.     shl    ebx,4
  948.     lea    eax,[ebx][Dword ptr Buffer][3]
  949.     mov    dr0,eax
  950.     add    eax,10h
  951.     mov    dr1,eax
  952.     add    eax,10h
  953.     mov    dr2,eax
  954.     add    eax,10h
  955.     mov    dr3,eax
  956.     mov    Loadall_Tbl._DR7,111102aah
  957.     LOADALL
  958.  
  959. @Test_DRBW:
  960.     rep    stosb
  961.     Lidt    fword ptr RM_IDT3_Ptr
  962.     mov    ebx,cr0
  963.     and    bl,not 1
  964.     mov    cr0,ebx
  965.     FARJMP    <@F>,<seg _text>
  966.  
  967. @@:    and    si,0fh
  968.     cmp    si,0fh            ; pass all breakpoints?
  969.     je    short @T7P        ; yep
  970.     Print_String    failed
  971.     jmp    @Test9
  972.  
  973. @T7P:    cmp    dx,4            ; INT01 4 times?
  974.     jne    @B
  975.     Print_String    passed
  976.  
  977. @Test9:
  978.     jmp    Loadall_ret
  979.  
  980.  
  981. LOADALL_386    endp
  982.  
  983.  
  984. ;---------------------------------------------------------------
  985. ; Minimal exception 13 handler that points past a 4-byte opcode,
  986. ; and sets the lowest bit in DI before returning.
  987. ;---------------------------------------------------------------
  988.     INT13    label    word
  989.     push    bp
  990.     mov    bp,sp
  991.     add    word ptr [bp][4],4
  992.     or    si,1
  993.     pop    bp
  994.     add    sp,2
  995.     iret
  996.  
  997.  
  998. ;-----------------------------------------------------------------------------
  999.   INT01:    ; Int1 trap routine
  1000. ;-----------------------------------------------------------------------------
  1001. ; Interprets breakpoint type, and sets a flag
  1002. ;-----------------------------------------------------------------------------
  1003.     inc    dx
  1004.     push    bp
  1005.     mov    bp,sp
  1006.     mov    buffer2[bx],cx
  1007.     add    bx,2
  1008.     push    eax
  1009.     push    ebx
  1010.     push    ecx
  1011.     mov    eax,dr6
  1012.     mov    ecx,eax
  1013.     mov    ebx,dr7
  1014.     shr    ebx,10h         ; get length encodings
  1015.     test    ah,20h            ; debug register access attempt?
  1016.     jnz    @DR_Attempt        ; yep
  1017.     shr    al,1            ; DR0?
  1018.     jc    @DR0
  1019.     shr    al,1            ; DR1?
  1020.     jc    @DR1
  1021.     shr    al,1            ; DR2?
  1022.     jc    @DR2
  1023. @DR3:    or    si,8
  1024.     and    cl,not 8
  1025.     test    bh,30h            ; code, or data?
  1026.     jz    @Fault
  1027.     jmp    short @Trap
  1028. @DR2:    or    si,4
  1029.     and    cl,not 4
  1030.     test    bh,03h            ; code, or data?
  1031.     jz    @Fault
  1032.     jmp    short @Trap
  1033. @DR1:    or    si,2
  1034.     and    cl,not 2
  1035.     test    bl,30h            ; code, or data?
  1036.     jz    @Fault
  1037.     jmp    short @Trap
  1038. @DR0:    or    si,1
  1039.     and    cl,not 1
  1040.     test    bl,03h            ; code, or data?
  1041.     jz    @Fault
  1042.     jmp    short @Trap
  1043. @Fault: add    word ptr [bp][2],1
  1044.     mov    dr6,ecx
  1045. @Trap:    pop    ecx
  1046.     pop    ebx
  1047.     pop    eax
  1048.     pop    bp
  1049.     iret
  1050.  
  1051. @Dr_Attempt:
  1052.     push    bp
  1053.     add    word ptr [bp][2],3
  1054.     pop    bp
  1055.     iret
  1056.  
  1057.  
  1058.  
  1059.  
  1060. ;-----------------------------------------------------------------------------
  1061.   Save_state    proc    near    ; Save the machine state before LOADALL
  1062. ;-----------------------------------------------------------------------------
  1063.     push    eax
  1064.     push    ds
  1065.     mov    si,0
  1066.     mov    di,offset Machine_State.GS_Desc
  1067.     mov    ax,5000h        ; GS descriptor
  1068.     mov    ds,ax
  1069.     mov    ebx,05050505h
  1070.     movsd
  1071.     mov    dword ptr [si-4],ebx
  1072.  
  1073.     sub    ax,1000h        ; FS descriptor
  1074.     sub    ebx,01010101h
  1075.     mov    si,0
  1076.     add    di,8
  1077.     mov    ds,ax
  1078.     movsd
  1079.     mov    dword ptr [si-4],ebx
  1080.     sub    ax,2000h        ; DS descriptor
  1081.     sub    ebx,02020202h
  1082.     mov    si,0
  1083.     add    di,8
  1084.     mov    ds,ax
  1085.     movsd
  1086.     mov    dword ptr [si-4],ebx
  1087.     add    ax,4000h        ; SS descriptor
  1088.     add    ebx,04040404h
  1089.     mov    si,0
  1090.     add    di,8
  1091.     mov    ds,ax
  1092.     movsd
  1093.     mov    dword ptr [si-4],ebx
  1094.     sub    ax,3000h        ; ES descriptor
  1095.     sub    ebx,03030303h
  1096.     mov    si,0
  1097.     add    di,14h
  1098.     mov    ds,ax
  1099.     movsd
  1100.     mov    dword ptr [si-4],ebx
  1101.     pop    ds
  1102.  
  1103.     mov    eax,cr0
  1104.     mov    Machine_State._CR0,eax
  1105.     pushfd
  1106.     pop    eax
  1107.     mov    Machine_State._Eflags,eax
  1108.     pop    eax
  1109.     mov    Machine_State._EDI,edi
  1110.     mov    Machine_State._ESI,esi
  1111.     mov    Machine_State._EBP,ebp
  1112.     mov    Machine_State._EBX,ebx
  1113.     mov    Machine_State._EDX,edx
  1114.     mov    Machine_State._ECX,ecx
  1115.     mov    Machine_State._EAX,eax
  1116.     mov    ax,gs
  1117.     movzx    eax,ax
  1118.     mov    Machine_State._GS,eax
  1119.     mov    ax,fs
  1120.     mov    Machine_State._FS,eax
  1121.     mov    ax,ds
  1122.     mov    Machine_State._DS,eax
  1123.     mov    ax,es
  1124.     mov    Machine_State._ES,eax
  1125.     ret
  1126. Save_state    endp
  1127.  
  1128.  
  1129. ;-----------------------------------------------------------------------------
  1130.   Restore_state proc    near    ; Restore the machine state after LOADALL
  1131. ;-----------------------------------------------------------------------------
  1132.     mov    ax,_data
  1133.     mov    ds,ax
  1134.     mov    ax,5000h        ; GS
  1135.     mov    es,ax
  1136.     mov    si,offset Machine_State.GS_Desc
  1137.     mov    di,0
  1138.     movsd
  1139.     sub    ax,1000h        ; FS
  1140.     add    si,8
  1141.     mov    di,0
  1142.     mov    es,ax
  1143.     movsd
  1144.     sub    ax,2000h        ; DS
  1145.     add    si,8
  1146.     mov    di,0
  1147.     mov    es,ax
  1148.     movsd
  1149.     add    ax,4000h        ; SS
  1150.     add    si,8
  1151.     mov    di,0
  1152.     mov    es,ax
  1153.     movsd
  1154.     sub    ax,3000h        ; ES
  1155.     add    si,14h
  1156.     mov    di,0
  1157.     mov    es,ax
  1158.     movsd
  1159.     mov    eax,Machine_State._ES
  1160.     mov    es,ax
  1161.     mov    eax,Machine_State._DS
  1162.     mov    ds,ax
  1163.     mov    eax,Machine_State._FS
  1164.     mov    fs,ax
  1165.     mov    eax,Machine_State._GS
  1166.     mov    gs,ax
  1167.     mov    eax,Machine_State._Eflags
  1168.     push    eax
  1169.     popfd
  1170.     mov    eax,Machine_State._CR0
  1171.     mov    cr0,eax
  1172.     mov    eax,Machine_State._EAX
  1173.     mov    ecx,Machine_State._ECX
  1174.     mov    edx,Machine_State._EDX
  1175.     mov    ebx,Machine_State._EBX
  1176.     mov    ebp,Machine_State._EBP
  1177.     mov    esi,Machine_State._ESI
  1178.     mov    edi,Machine_State._EDI
  1179.     ret
  1180. Restore_State    endp
  1181.  
  1182.  
  1183. ;---------------------------------------------------------------
  1184. ; Include the CPU_TYPE procedure & LOADALL test
  1185. ;---------------------------------------------------------------
  1186.     Include CPU_TYPE.ASM
  1187.  
  1188. _text    ends
  1189.  
  1190.  
  1191.     stack    segment para stack 'stack'
  1192.     db    400h dup (0)
  1193.     stack    ends
  1194.  
  1195.     end    LOADALL_386
  1196.  
  1197.