home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / msj / msjv2_1 / ems / ems.asm < prev    next >
Encoding:
Assembly Source File  |  1989-02-28  |  16.6 KB  |  404 lines

  1. ; ============================================================================
  2. ; ============================================================================
  3. ; Figure 8: Kernel Module
  4.  
  5. ; ============================================================================
  6.  
  7. CODE    SEGMENT PARA PUBLIC 'CODE'
  8. ORG     100h
  9. ASSUME  CS:CODE, DS:DATA, ES:NOTHING, SS:STACK
  10.  
  11. max_proc_entries              EQU        64
  12.                               
  13. pseudo_over_struct            STRUC
  14.       proc_data_segment       DW        ?
  15.       proc_extra_segment      DW        ?
  16.       proc_entry_count        DW        ?
  17.       proc_entry_ptr          DD max_proc_entries DUP (?)
  18. pseudo_over_struct            ENDS
  19.  
  20. main  PROC  NEAR
  21.  
  22.       MOV   AX, DATA                       ; Segment initialization
  23.       MOV   DS, AX
  24.  
  25. check_for_emm_loaded:
  26.       CALL  test_for_EMM                   ; Use the "interrupt vector"
  27.       JE    get_emm_page_frame             ; technique to determine
  28.       JMP   emm_err_exit                   ; whether EMM is loaded
  29.  
  30. get_emm_page_frame:
  31.       MOV   AH, 41h                        ; Get the page frame base
  32.       INT   67h                            ; address from EMM
  33.       OR    AH, AH
  34.       JZ    allocate_64K
  35.       JMP   emm_err_exit
  36.  
  37. allocate_64K:
  38.       MOV   exp_mem_segment, BX            ; Allocate 4 pages of expand-
  39.       MOV   AH, 43h                        ; ed memory for this example.
  40.       MOV   BX, 4                          ; More can be allocated de-
  41.       INT   67h                            ; pending on the number of
  42.       OR    AH, AH                         ; overlays to be loaded.
  43.       JZ    map_64K                        ; Actually, in this case,
  44.       JMP   emm_err_exit                   ; only a single page is re-
  45.                                            ; quired because the example
  46.                                            ; pseudo-overlay is extreme-
  47.                                            ; ly small.
  48. map_64K:
  49.       MOV   handle, DX                     ; Map in the first 4 logical
  50.       MOV   CX, 4                          ; pages at physical pages 0
  51. map_pages_loop:                            ; through 3
  52.       MOV   AH, 44h                        ;    logical page 0 at
  53.       MOV   BX, CX                         ;       physical page 0
  54.       DEC   BX                             ;    logical page 1 at
  55.       MOV   AL, BL                         ;       physical page 1
  56.       MOV   DX, handle                     ;    logical page 2 at
  57.       INT   67h                            ;       physical page 2
  58.       OR    AH, AH                         ;    logical page 3 at 
  59.       LOOPE map_pages_loop                 ;       physical page 3
  60.       JE    init_load_struct               ; If additional overlays were
  61.       JMP   emm_err_exit                   ; required, each overlay 
  62.                                            ; would be loaded after map-
  63.                                            ; ping and a new set of
  64.                                            ; logical pages would be
  65.                                            ; mapped at the same
  66.                                            ; physical pages.
  67.  
  68. init_load_struct:
  69.       MOV   ES, exp_mem_segment            ; Initialize pseudo-overlay
  70.       MOV   DI, 0                          ; environment and procedure
  71.       MOV   CX, (SIZE pseudo_over_struct)  ; pointer area. This struc-
  72.       MOV   AL, 0                          ; ture begins at the page 
  73.       REP   STOSB                          ; frame segment address.
  74.  
  75.       MOV   AX, (SIZE pseudo_over_struct)  ; Compute the load address
  76.       ADD   AX, 000Fh                      ; within expanded memory for
  77.       AND   AX, 0FFF0h                     ; the overlay. The address is
  78.       MOV   CX, 4                          ; rounded up to the next
  79.       SHR   AX, CL                         ; higher paragraph boundary
  80.       ADD   AX, exp_mem_segment            ; immediately following the
  81.       MOV   parm_block.load_segment, AX    ; pseudo-overlay environment
  82.       MOV   parm_block.reloc_factor, AX    ; & procedure pointer
  83.                                            ; structure. This computa-
  84.                                            ; tion takes into account
  85.                                            ; the maximum number of
  86.                                            ; procedure entry points
  87.                                            ; which the pseudo-overlay
  88.                                            ; is going to return to
  89.                                            ; this program.
  90.  
  91.       MOV   WORD PTR entry_point[0], 100h  ; Build .COM file entry
  92.       MOV   WORD PTR entry_point[2], AX    ; point
  93.  
  94.       MOV   AH, 4Bh                        ; Load the pseudo-overlay
  95.       MOV   AL, 03h                        ; using the DOS "load
  96.       LEA   DX, pseudo_over_name           ; overlay" function
  97.       PUSH  DS
  98.       POP   ES
  99.       LEA   BX, parm_block
  100.       INT   21h
  101.       JC    emm_err_exit
  102.  
  103.       PUSH  DS                             ; Transfer control to the
  104.       PUSH  ES                             ; loaded pseudo-overlays
  105.       CALL  DWORD PTR entry_point          ; initialization code
  106.       POP   ES
  107.       POP   DS
  108.       OR    AH, AH
  109.       JZ    call_over_procedures
  110.       JMP   emm_err_exit
  111.  
  112. call_over_procedures:
  113.       MOV   ES, exp_mem_segment            ; As an example of passing
  114.       MOV   BX, 0                          ; control to a procedure
  115.       MOV   DI, 0                          ; existing in expanded
  116.       MOV   CX, ES:[BX].proc_entry_count   ; memory, each procedure con-
  117.       JCXZ  deallocate_exp_memory          ; tained in the overlay will
  118.                                            ; be called in sequence.
  119.                                            ; Obviously, a single pro-
  120.                                            ; cedure could be called
  121.                                            ; just as easily.
  122.  
  123. pseudo_over_call_loop:
  124.       PUSH  BX
  125.       PUSH  CX
  126.       PUSH  DI
  127.       PUSH  ES
  128.       PUSH  DS
  129.  
  130.       LDS   AX, ES:[BX+DI].proc_entry_ptr
  131.       MOV   WORD PTR CS:tp_ent_ptr[0], AX
  132.       MOV   WORD PTR CS:tp_ent_ptr[2], DS
  133.  
  134.       MOV   AX, 123                        ; Pass 2 numbers to
  135.       MOV   DX, 23                         ; the procedures
  136.  
  137.       MOV   DS, ES:[BX].proc_data_segment  ; Set up pseudo-overlays
  138.       MOV   ES, ES:[BX].proc_extra_segment ; segment environment
  139.       CALL  DWORD PTR CS:tp_ent_ptr        ; Call each procedure
  140.  
  141.       POP   DS
  142.       POP   ES
  143.       POP   DI
  144.       POP   CX
  145.       POP   BX
  146.  
  147.       ADD   DI, 4                          ; Adjust index to the next
  148.       LOOP  pseudo_over_call_loop          ; procedure (4 bytes long)
  149.                                            ; pointer & loop till all
  150.                                            ; have been called
  151.  
  152. deallocate_exp_memory:
  153.       MOV   AH, 45h                        ; Return the allocated
  154.       MOV   DX, handle                     ; pages to the expanded
  155.       INT   67h                            ; memory manager
  156.       OR    AH, AH
  157.       JNZ   emm_err_exit
  158.  
  159. exit:
  160.       MOV   AH, 4Ch                        ; Return a normal exit code
  161.       MOV   AL, 0
  162.       INT   21h
  163.  
  164. emm_err_exit:
  165.       MOV   AL, AH                         ; Display the fact that
  166.       MOV   AH, 09h                        ; an EMM error occurred
  167.       LEA   DX, emm_err_msg                ; Go to the normal exit
  168.       INT   21h
  169.       JMP   exit
  170.  
  171.       tp_ent_ptr              DD        ?  ; CS relative far pointer
  172.                                            ; used for transfer to the
  173. main  ENDP                                 ; procedures in the
  174.                                            ; pseudo_overlay
  175.  
  176.  
  177. ; ============================================================================
  178. ; ============================================================================
  179. ; Figure 9: Procedure to Test for the Presence of EMM 
  180.  
  181. ; ============================================================================
  182.  
  183. test_for_EMM    PROC NEAR
  184.  
  185.        MOV     AX, 3567h              ; Issue "get interrupt vector"
  186.        INT     21h
  187.  
  188.        MOV     DI, 000Ah              ; Use the SEGMENT in ES
  189.                                       ; returned by DOS, place
  190.                                       ; the "device name field"
  191.                                       ; OFFSET in DI.
  192.  
  193.        LEA     SI, EMM_device_name    ; Place the OFFSET of the EMM
  194.                                       ; device name string in SI,
  195.                                       ; the SEGMENT is already in DS.
  196.  
  197.        MOV     CX, 8                  ; Compare the name strings
  198.        CLD                            ; Return the status of the
  199.        REPE    CMPSB                  ; compare in the ZERO flag
  200.        RET
  201.  
  202. test_for_EMM ENDP
  203.  
  204. CODE        ENDS
  205.  
  206. ; ============================================================================
  207. ; ============================================================================
  208. ; Figure 10: Pseudo-overlay Module
  209.  
  210. ; ============================================================================
  211.  
  212. CODE    SEGMENT PARA PUBLIC 'CODE'
  213. ASSUME  CS:CODE, DS:DATA
  214. ORG     100h
  215.  
  216. actual_proc_entries         EQU         2
  217.  
  218. overlay_entry_struct        STRUC
  219.         proc_data_segment   DW          ?
  220.         proc_extra_segment  DW          ?
  221.         proc_entry_count    DW          ?
  222.         proc_entry_ptr      DD          actual_proc_entries DUP (?)
  223. overlay_entry_struct        ENDS
  224.  
  225. ; ============================================================================
  226. ; ============================================================================
  227. ; Figure 11: Procedure to Identify Overlay
  228.  
  229. ; ============================================================================
  230.  
  231. command_line_entry_point        PROC        NEAR
  232.  
  233.         MOV     AX, DATA                    ; Set up local data
  234.         MOV     DS, AX                      ; segment
  235.  
  236.         LEA     DX, overlay_err_msg         ; Display overlay error
  237.         MOV     AH, 09h                     ; message
  238.         INT     21h                
  239.  
  240.         MOV     AX, 4C00h                   ; Exit back to DOS
  241.         INT     21h
  242.  
  243. command_line_entry_point        ENDP
  244.  
  245. ; ============================================================================
  246. ; ============================================================================
  247. ; Figure 12: Data Segment for the Pseudo-overlay Module
  248.  
  249. ; ============================================================================
  250.  
  251. DATA  SEGMENT PARA PUBLIC 'DATA'
  252.  
  253. sum_msg         DB   0Dh, 0Ah, 'Sum of numbers = ', '$'
  254. diff_msg        DB   0Dh, 0Ah, 'Difference of numbers = ', '$'
  255. overlay_err_msg DB   'Overlay cannot be executed via the command line$'
  256. powers_of_ten   DW   10000, 1000, 100, 10, 1
  257.  
  258. DATA  ENDS
  259.  
  260. END   command_line_entry_point
  261.  
  262. ; ============================================================================
  263. ; ============================================================================
  264. ; Figure 13: Pseudo-overlay Data Structure Initialization Procedure
  265.  
  266. ; ============================================================================
  267.  
  268. initialization  PROC    FAR
  269.  
  270. MOV  AX, DATA                                        ; Set up a local
  271. MOV  DS, AX                                          ; data segment
  272.  
  273. MOV  AH, 41h                                         ; Get the page 
  274. INT  67h                                             ; frame segment
  275. OR   AH, AH                                          ; address from EMM
  276. JNZ  error       
  277.  
  278. MOV  ES, BX                                          ; Create a pointer 
  279. MOV  DI, 0                                           ; to the expanded
  280.                                                      ; memory page frame
  281.                                                      ; segment address
  282.  
  283. MOV  ES:[DI].proc_data_segment, DS                   ; Return local data 
  284. MOV  ES:[DI].proc_extra_segment, DS                  ; & extra segment 
  285.                                                      ; back to the kernel
  286.  
  287. MOV  WORD PTR ES:[DI].proc_entry_count, 2            ; Return the number
  288.                                                      ; of local call-
  289.                                                      ; able procedures
  290.                                                      ; back to kernel
  291. MOV  WORD PTR ES:[DI].proc_entry_ptr[0], OFFSET sum  ; Return a far
  292. MOV  WORD PTR ES:[DI].proc_entry_ptr[2], SEG    sum  ; pointer to each
  293. MOV  WORD PTR ES:[DI].proc_entry_ptr[4], OFFSET diff ; local callable
  294. MOV  WORD PTR ES:[DI].proc_entry_ptr[6], SEG    diff ; procedure in the
  295.                                                      ; pseudo-overlay
  296.                                                      ; back to kernel
  297.  
  298. exit:  MOV   AH, 0                                   ; Set status in AH
  299.                                                      ; = passed
  300. error: RET                                           ; Return status
  301.                                                      ; in AH
  302.  
  303. initialization  ENDP
  304.  
  305. ; ============================================================================
  306. ; ============================================================================
  307. ; Figure 14: Procedure to Add AX and DX
  308.  
  309. ; ============================================================================
  310.  
  311. sum     PROC    FAR
  312.  
  313.         ADD     AX, DX                 ; Add numbers
  314.         PUSH    AX                     ; Display sum message
  315.         LEA     DX, sum_msg
  316.         MOV     AH, 09h
  317.         INT     21h
  318.         POP     AX
  319.         CALL    display_result         ; Display sum
  320.         RET
  321.  
  322. sum     ENDP
  323.  
  324. ; ============================================================================
  325. ; ============================================================================
  326. ; Figure 15: Procedure to Subtract AX and DX
  327.  
  328. ; ============================================================================
  329.  
  330. diff    PROC    FAR
  331.  
  332.         SUB     AX, DX               ; Subtract numbers
  333.         PUSH    AX                   ; Display difference message
  334.         LEA     DX, diff_msg
  335.         MOV     AH, 09h
  336.         INT     21h
  337.         POP     AX
  338.         CALL    display_result       ; Display difference
  339.         RET
  340.  
  341. diff    ENDP
  342.  
  343. ; ============================================================================
  344. ; ============================================================================
  345. ; Figure 16: Procedure to Display Number in AX in Decimal
  346.  
  347. ; ============================================================================
  348.  
  349. display_result  PROC    NEAR
  350.  
  351.         LEA     DI, powers_of_ten
  352.         MOV     CX, 5
  353. display_loop:
  354.         XOR     DX, DX            ; Divide the number passed
  355.         DIV     WORD PTR [DI]     ; in AX by descending powers of ten
  356.         ADD     AL, '0'           ; Convert digit to ASCII
  357.  
  358.         PUSH    DX                ; Output the digit
  359.         MOV     DL, AL
  360.         MOV     AH, 02h
  361.         INT     21h
  362.         POP     AX
  363.  
  364.         ADD     DI, 2
  365.         LOOP    display_loop
  366.         RET
  367.  
  368. display_result        ENDP
  369.  
  370. ; ============================================================================
  371. ; ============================================================================
  372. ; Figure 17: Data and Stack Segment for the Kernel and the Pseudo-overlay
  373.  
  374. ; ============================================================================
  375.  
  376. DATA            SEGMENT PARA PUBLIC 'DATA'
  377.  
  378. emm_err_msg        DB    'EMM error occurred$' ; EMM diagnostic message
  379. pseudo_over_name   DB    'OVERLAY.EXE', 0      ; Name of pseudo-overlay
  380. EMM_device_name    DB    'EMMXXXX0'            ; Standard EMM device name
  381. exp_mem_segment    DW    ?                     ; Temp for expanded
  382.                                                ; memory page frame
  383.                                                ; segment address
  384. handle             DW    ?                     ; Temp for handle allo-
  385.                                                ; cated to the kernel
  386. entry_point  DD          ?                     ; Far pointer to the 
  387.                                                ; entry point for a .COM 
  388.                                                ; file
  389. parm_block_struct  STRUC                       ; Structure definition 
  390.     load_segment   DW    ?                     ; for a "load overlay" 
  391.     reloc_factor   DW    ?                     ; parameter block
  392. parm_block_struct  ENDS
  393. parm_block         parm_block_struct <>        ; The actual parameter
  394.                                                ; block
  395.  
  396. DATA        ENDS
  397.  
  398.  
  399. STACK   SEGMENT PARA STACK 'STACK'
  400.         local_stack     DW 256 DUP ('^^')
  401. STACK   ENDS
  402.  
  403. END        main
  404.