home *** CD-ROM | disk | FTP | other *** search
/ Interativa 1 / MEGAZINE.iso / programa / c / ztimer23 / include / model.mac < prev    next >
Encoding:
Text File  |  1996-03-27  |  20.8 KB  |  762 lines

  1. ;****************************************************************************
  2. ;*
  3. ;*                  Copyright (C) 1996 SciTech Software.
  4. ;*                          All rights reserved.
  5. ;*
  6. ;* Filename:    $Workfile:   model.mac  $
  7. ;* Version:     $Revision:   1.1  $
  8. ;*
  9. ;* Language:    Turbo Assembler 3.0
  10. ;* Environment: IBM PC (MS DOS)
  11. ;*
  12. ;* Description: Macros to provide memory model independant assembly language
  13. ;*              module for C programming. Supports the large memory model
  14. ;*              and 386 extended memory models.
  15. ;*
  16. ;*              The defines that you should use when assembling modules that
  17. ;*                use this macro package are:
  18. ;*
  19. ;*                    __LARGE__    Assemble for 16 bit large model
  20. ;*                    __COMPACT__    Assemble for 16 bit model
  21. ;*                  __WINDOWS16__ Assemble for Hybrid 16/32 bit PM large model
  22. ;*                  __X386__    Assemble for 386 extended memory model
  23. ;*                  __FLAT__    Assemble for 386 FLAT memory model
  24. ;*                  __8086__    Assemble for 8086 real mode code
  25. ;*                    __80286__    Assemble for 80286 real mode code
  26. ;*                    __COMM__    Declare global variables as COMMunal
  27. ;*                  ES_NOT_DS   Assemble assuming ES != DS for 32 bit code
  28. ;*                  BUILD_DLL   Assembler for use in a DLL
  29. ;*
  30. ;*                By default the real mode LARGE memory model targeted for the
  31. ;*                80386 processor is selected.
  32. ;*
  33. ;*              Note that we use the TASM simplified segment directives so
  34. ;*              that 32 bit code will assemble correctly, and we also use
  35. ;*              TASM's IDEAL mode syntax, so this is not compatible with
  36. ;*              MASM. The __FLAT__ mode should be used whenever possible to
  37. ;*              assemble code that needs to be converted to Unix style .o
  38. ;*              files for DJGPP and EMX, and for most new compilers. Symantec
  39. ;*              C++ however requires the __X386__ memory model, or it will
  40. ;*                not link correctly). You should specify either of __X386__ or
  41. ;*              __FLAT__ to assemble code correctly.
  42. ;*
  43. ;*                The main intent of the macro file is to enable programmers
  44. ;*                to write _one_ set of source that can be assembled to run
  45. ;*                in either 16 bit real and protected modes or 32 bit
  46. ;*                protected mode without the need to riddle the code with
  47. ;*                'if flatmodel' style conditional assembly (it is still there
  48. ;*                but nicely hidden by a macro layer that enhances the
  49. ;*                readability and understandability of the resulting code).
  50. ;*
  51. ;* NOTES:   When you declare the data and code segments, you should specify
  52. ;*          a name to be used. This name should be the name of the file
  53. ;*          being assembled, but you may use the same name for mutiple
  54. ;*          modules if you wish so that the data and code for these modules
  55. ;*          are all contained in the same segments. Of course the maximum
  56. ;*          size of data and code must be less than 64k respectively.
  57. ;*
  58. ;* $Date:   27 Mar 1996 19:35:26  $ $Author:   KendallB  $
  59. ;*
  60. ;****************************************************************************
  61.  
  62.         IDEAL
  63.  
  64. ; Define the __WINDOWS__ symbol if we are compiling for any Windows
  65. ; environment
  66.  
  67. ifdef    __WINDOWS16__
  68. __WINDOWS__ = 1
  69. endif
  70. ifdef    __WINDOWS32__
  71. __WINDOWS__ = 1
  72. endif
  73.  
  74. ; Define symbols codesize and datasize depending on the requested memory
  75. ; model. Note that because of the differences in addressing used in the
  76. ; 16 and 32 bit memory models, we need a couple of macros to define things
  77. ; such as what register is used for looping (CX or ECX) etc. Note that we
  78. ; can use simple 16 bit code in 32 bit mode and vice-versa, but unless this
  79. ; is absolutely necessary it poses the performance hit of requiring an
  80. ; operand size prefex for the instruction. Hence if we simply need to use
  81. ; a set of registers for an operation, use the macros to use the best
  82. ; register for the current mode of operation. Of course the real registers
  83. ; may be specified for operations that specifically require 16 or 32 bits.
  84. ;
  85. ; The following things are defined:
  86. ;
  87. ;    UCHAR    - Typedef for a character type
  88. ;   USHORT - Typedef for a short type
  89. ;    UINT    - Typedef for an integer type
  90. ;    BOOL    - Typedef for a boolean type
  91. ;   DPTR    - Operand size of data pointers
  92. ;   DDIST   - Distance to data variables (NEAR or FAR)
  93. ;   CPTR    - Operand size of code pointers
  94. ;    FCPTR    - Operand size of far code pointers
  95. ;    NCPTR    - Operand size of near code pointers
  96. ;   FPTR    - Function pointer modifier, either NEAR or FAR
  97. ;    _AX        - General accumulator register, either AX or EAX
  98. ;    _BX        - General base register, either BX or EBX
  99. ;   _CX        - Loop counter register, either CX or ECX
  100. ;   CXPTR   - Operand size of loop counter, either WORD or DWORD
  101. ;   _DX        - General data register, either DX or EDX
  102. ;    _SI        - Source index register, either SI or ESI
  103. ;    _DI        - Destination index register, either DI or EDI
  104. ;    _BP        - Base pointer register, either BP or EBP
  105. ;    _SP        - Stack pointer register, either SP or ESP
  106. ;    _ES        - ES segment override - evaluates to nothing in 32 bit PM
  107.  
  108. ifdef   __FLAT__
  109.         __X386__ = 1
  110. endif
  111.  
  112. ifdef   __X386__
  113.         flatmodel    EQU    1        ; This is a flat memory model
  114.         pmode        EQU    1        ; This is a protected mode memory model
  115.         intsize        EQU    4        ; Size of an integer
  116.         datasize    EQU 0       ; Near data memory model
  117.         dptrsize    EQU 4       ; Size of a data pointer (32 bit near)
  118.         stack_align EQU 4
  119.         typedef UCHAR BYTE        ; Size of a character
  120.         typedef USHORT WORD        ; Size of a short
  121.         typedef UINT DWORD        ; Size of an integer
  122.         typedef ULONG DWORD        ; Size of a long
  123.         typedef BOOL DWORD      ; Size of a boolean
  124.         typedef DPTR DWORD        ; Size of a data pointer
  125.         typedef FDPTR FWORD        ; Size of a far data pointer
  126.         typedef    NDPTR DWORD        ; Size of a near data pointer
  127.         DDIST       EQU NEAR
  128.         codesize    EQU 0       ; Near code memory model
  129.         cptrsize    EQU 4
  130.         typedef CPTR DWORD        ; Size of a code pointer
  131.         typedef FCPTR FWORD        ; Size of a far code pointer
  132.         typedef NCPTR DWORD        ; Size of a near code pointer
  133.         FPTR        EQU NEAR
  134.         _AX            EQU    EAX        ; EAX is used for accumulator
  135.         _BX            EQU    EBX        ; EBX is used for accumulator
  136.         _CX            EQU ECX     ; ECX is used for looping
  137.         CXPTR        EQU    DWORD    ; loop variables are 32 bits
  138.         _DX            EQU    EDX        ; EDX is used for data register
  139.         _SI            EQU    ESI        ; ESI is the source index register
  140.         _DI            EQU    EDI        ; EDI is the destination index register
  141.         _BP            EQU    EBP        ; EBP is used for base pointer register
  142.         _SP            EQU    ESP        ; ESP is used for stack pointer register
  143.         _ES            EQU            ; ES and DS are the same in 32 bit PM
  144.         P386                    ; Turn on 386 code generation
  145. ifdef   __FLAT__
  146.         MODEL       FLAT        ; Set up for 32 bit simplified FLAT model
  147.         S_UCHAR        EQU    UCHAR
  148.         S_USHORT    EQU    USHORT
  149.         S_BOOL         EQU    BOOL
  150. else
  151. ; The following is for Symantec C++ which wont link with code assembled in
  152. ; the FLAT model (stuffed if I know why), but TASM does not correctly set
  153. ; the size of WORD arguments on the stack to 4 bytes, so we create a set
  154. ; of macros to do this for us.
  155.         LARGESTACK              ; Set up for a 32 bit stack model
  156.         S_UCHAR        EQU    BYTE:4
  157.         S_USHORT    EQU    WORD:2
  158.         S_BOOL      EQU BOOL
  159. endif
  160. else
  161.         flatmodel    EQU    0        ; This is a segmented memory model
  162. ifdef   __WINDOWS16__
  163.         pmode        EQU    1        ; This is a protected mode memory model
  164. else
  165.         pmode        EQU    0        ; This is a real mode memory model
  166. endif
  167.         intsize        EQU    2        ; Size of an integer
  168.         datasize    EQU 1       ; Far data memory model
  169.         dptrsize    EQU 4       ; Size of a data pointer
  170.         stack_align EQU 2
  171.         typedef UCHAR BYTE      ; Size of a character
  172.         typedef USHORT WORD        ; Size of a short
  173.         typedef UINT WORD        ; Size of an integer
  174.         typedef ULONG DWORD        ; Size of a long
  175.         typedef BOOL WORD        ; Size of a boolean
  176.         typedef DPTR DWORD        ; Size of a data pointer
  177.         typedef FDPTR DWORD        ; Size of a far data pointer
  178.         typedef    NDPTR WORD        ; Size of a near data pointer
  179.         DDIST       EQU FAR
  180. ifdef    __COMPACT__
  181.         codesize    EQU 0       ; Near code memory model
  182.         cptrsize    EQU 2       ; Size of a code pointer
  183.         typedef CPTR WORD        ; Size of a code pointer
  184.         typedef FCPTR DWORD        ; Size of a far code pointer
  185.         typedef NCPTR WORD        ; Size of a near code pointer
  186.         FPTR        EQU NEAR
  187. else
  188.         codesize    EQU 1       ; Far code memory model
  189.         cptrsize    EQU 4       ; Size of a code pointer
  190.         typedef CPTR DWORD        ; Size of a code pointer
  191.         typedef FCPTR DWORD        ; Size of a far code pointer
  192.         typedef NCPTR WORD        ; Size of a near code pointer
  193.         FPTR        EQU FAR
  194. endif
  195.         _AX            EQU    AX        ; AX is used for accumulator
  196.         _BX            EQU    BX        ; BX is used for accumulator
  197.         _CX            EQU CX         ; CX is used for looping
  198.         CXPTR        EQU    WORD    ; loop variables are 16 bits
  199.         _DX            EQU    DX        ; DX is used for data register
  200.         _SI            EQU    SI        ; SI is the source index register
  201.         _DI            EQU    DI        ; DI is the destination index register
  202.         _BP            EQU    BP        ; BP is used for base pointer register
  203.         _SP            EQU    SP        ; SP is used for stack pointer register
  204.         _ES            EQU es:        ; ES is used for segment override
  205.         S_UCHAR        EQU    UCHAR
  206.         S_USHORT    EQU    USHORT
  207.         S_BOOL         EQU    BOOL
  208. ifndef    __8086__
  209. ifdef    __80286__
  210.         P286                    ; Turn on 286 code generation
  211. else
  212.         P386                    ; Turn on 386 code generation
  213. endif
  214. endif
  215. endif
  216.  
  217. ; Provide a typedef for real floating point numbers
  218.  
  219. ifdef    DOUBLE
  220.         typedef REAL QWORD
  221. else
  222.         typedef    REAL DWORD
  223. endif
  224.  
  225. ; Macros for declaring external global variables
  226.  
  227. ifdef   __COMM__
  228. MACRO   $EXTRN      name,type
  229.         COMM        DDIST name:type
  230. ENDM
  231. else
  232. MACRO   $EXTRN      name,type
  233.         EXTRN       name:type
  234. ENDM
  235. endif
  236.  
  237. ; Macros for entering and exiting C callable functions. Note that we must
  238. ; always save and restore the SI and DI registers for C functions, and for
  239. ; 32 bit C functions we also need to save and restore EBX and clear the
  240. ; direction flag.
  241.  
  242. MACRO    save_c_regs
  243. ifdef    __X386__
  244.         push    ebx
  245. endif
  246.         push    _si
  247.         push    _di
  248. ENDM
  249.  
  250. MACRO    enter_c    LocalSize
  251.         push    _bp
  252.         mov     _bp,_sp
  253.     IFDIFI    <LocalSize>,<0>
  254.         sub        _sp,LocalSize
  255.     ENDIF
  256.         save_c_regs
  257. ENDM
  258.  
  259. MACRO    restore_c_regs
  260.         pop        _di
  261.         pop        _si
  262. ifdef    __X386__
  263.         pop        ebx
  264. endif
  265. ENDM
  266.  
  267. MACRO    leave_c
  268.         restore_c_regs
  269.         cld
  270.         mov     _sp,_bp
  271.         pop     _bp
  272. ENDM
  273.  
  274. MACRO    leave_c_nolocal
  275.         restore_c_regs
  276.         cld
  277.         pop     _bp
  278. ENDM
  279.  
  280. MACRO   use_ebx
  281. if flatmodel
  282.         push    ebx
  283. endif
  284. ENDM
  285.  
  286. MACRO   unuse_ebx
  287. if flatmodel
  288.         pop     ebx
  289. endif
  290. ENDM
  291.  
  292. ; Macros for saving and restoring the value of DS,ES,FS,GS when it is to
  293. ; be used in assembly routines. This evaluates to nothing in the flat memory
  294. ; model, but is saves and restores DS in the large memory model.
  295.  
  296. MACRO    use_ds
  297. ife flatmodel
  298.         push    ds
  299. endif
  300. ENDM
  301.  
  302. MACRO    unuse_ds
  303. ife flatmodel
  304.         pop        ds
  305. endif
  306. ENDM
  307.  
  308. MACRO    use_es
  309. ife flatmodel
  310.         push    es
  311. endif
  312. ENDM
  313.  
  314. MACRO    unuse_es
  315. ife flatmodel
  316.         pop        es
  317. endif
  318. ENDM
  319.  
  320. MACRO    use_fs
  321. ife flatmodel
  322.         push    fs
  323. endif
  324. ENDM
  325.  
  326. MACRO    unuse_fs
  327. ife flatmodel
  328.         pop        fs
  329. endif
  330. ENDM
  331.  
  332. ; Macros for loading the address of a data pointer into a segment and
  333. ; index register pair. The macro explicitly loads DS or ES in the 16 bit
  334. ; memory model, or it simply loads the offset into the register in the flat
  335. ; memory model since DS and ES always point to all addressable memory. You
  336. ; must use the correct _REG (ie: _BX) macros for documentation purposes.
  337.  
  338. MACRO    _lds    reg, addr
  339. if flatmodel
  340.         mov     reg,addr
  341. else
  342.         lds        reg,addr
  343. endif
  344. ENDM
  345.  
  346. MACRO   _les    reg, addr
  347. if flatmodel
  348.         mov     reg,addr
  349. else
  350.         les        reg,addr
  351. endif
  352. ENDM
  353.  
  354. ; Macros to use the FS register as a scratch segment register for 16 bit
  355. ; code. For 32 bit code we assume DS addresses the same area.
  356.  
  357. MACRO   _lfs    reg, addr
  358. if flatmodel
  359.         mov     reg,addr
  360. else
  361.         lfs        reg,addr
  362. endif
  363. ENDM
  364.  
  365. if flatmodel
  366.         _FS    EQU
  367. else
  368.         _FS    EQU    fs:
  369. endif
  370.  
  371. ; Macro to force the value of ES to be the same as DS for 32 bit assembler
  372. ; code. For most compilers this evaluates to nothing, but for Symantec C++
  373. ; we cant assume that DS == ES at all times (since Symantec uses a different
  374. ; selector for SS).
  375.  
  376. MACRO    force_es_eq_ds
  377. ifdef   ES_NOT_DS
  378.         push    ds                ; Force ES == DS for following code
  379.         pop        es
  380. endif
  381. ENDM
  382.  
  383. ; Macros for setting the value of the DS,ES,FS,GS registers to the same
  384. ; value. This does nothing in 32 bit protected mode, except for compilers
  385. ; that assume that DS != ES (Symantec C++ is one) and hence ES is always
  386. ; available to be loaded with any value you desire.
  387.  
  388. MACRO    es_eq_ds
  389. ife flatmodel
  390.         push    ds
  391.         pop        es
  392. endif
  393. ENDM
  394.  
  395. MACRO    ds_eq_es
  396. ife flatmodel
  397.         push    es
  398.         pop        ds
  399. endif
  400. ENDM
  401.  
  402. MACRO    ds_eq_ss
  403. ife flatmodel
  404.         push    ss
  405.         pop        ds
  406. else
  407. ifdef   ES_NOT_DS
  408.         push    ss
  409.         pop        ds
  410. endif
  411. endif
  412. ENDM
  413.  
  414. MACRO    fs_eq_ds
  415. ife flatmodel
  416.         push    ds
  417.         pop        fs
  418. endif
  419. ENDM
  420.  
  421. ; Macros for adding and subtracting a value from registers. Two value are
  422. ; provided, one for 16 bit modes and another for 32 bit modes (the extended
  423. ; register is used in 32 bit modes).
  424.  
  425. MACRO   _add    reg, val16, val32
  426. if flatmodel
  427.         add        e®&, val32
  428. else
  429.         add        reg, val16
  430. endif
  431. ENDM
  432.  
  433. MACRO    _sub    reg, val16, val32
  434. if flatmodel
  435.         sub        e®&, val32
  436. else
  437.         sub        reg, val16
  438. endif
  439. ENDM
  440.  
  441. ; Macro to clear the high order word for the 32 bit extended registers.
  442. ; This is used to convert an unsigned 16 bit value to an unsigned 32 bit
  443. ; value, and will evaluate to nothing in 16 bit modes.
  444.  
  445. MACRO    clrhi    reg
  446. if pmode
  447.         movzx    e®&,reg
  448. endif
  449. ENDM
  450.  
  451. MACRO    sgnhi    reg
  452. if pmode
  453.         movsx    e®&,reg
  454. endif
  455. ENDM
  456.  
  457. ; Macro to clear the high order word for the 32 bit extended registers.
  458. ; This is used to convert an unsigned 16 bit value to an unsigned 32 bit
  459. ; value in 16 bit real mode and PM USE32 code. For 32 bit FLAT model
  460. ; code it will evaluate to nothing.
  461.  
  462. MACRO    clrhi16    reg
  463. ife    flatmodel
  464.         movzx    e®&,reg
  465. endif
  466. ENDM
  467.  
  468. MACRO    sgnhi16    reg
  469. ife    flatmodel
  470.         movsx    e®&,reg
  471. endif
  472. ENDM
  473.  
  474. ; Macro to load an extended register with an integer value in either mode
  475.  
  476. MACRO    loadint    reg,val
  477. if flatmodel
  478.         mov        e®&,val
  479. else
  480.         xor        e®&,e®&
  481.         mov     reg,val
  482. endif
  483. ENDM
  484.  
  485. ; Macros to load and store integer values with string instructions
  486.  
  487. MACRO    LODSINT
  488. if flatmodel
  489.         lodsd
  490. else
  491.         lodsw
  492. endif
  493. ENDM
  494.  
  495. MACRO    STOSINT
  496. if flatmodel
  497.         stosd
  498. else
  499.         stosw
  500. endif
  501. ENDM
  502.  
  503. ; Macros for procedure definitions given a name. Note that they also export
  504. ; the symbol with the PUBLIC directive, so that it need not be explicitly
  505. ; exported.
  506.  
  507. MACRO   procstart name          ; Set up model independant proc
  508. if codesize
  509. PROC    name FAR
  510. else
  511. PROC    name NEAR
  512. endif
  513.         PUBLIC name
  514. ENDM
  515.  
  516. MACRO   procstartdll name       ; Set up DLL _export'ed proc
  517. if codesize
  518. PROC    name FAR
  519. else
  520. PROC    name NEAR
  521. endif
  522. ifdef   BUILD_DLL
  523.         PUBLICDLL name
  524. else
  525.         PUBLIC name
  526. endif
  527. ENDM
  528.  
  529. ; This macro sets up a procedure to be exported from a 16 bit DLL. Since the
  530. ; calling conventions are always _far _pascal for 16 bit DLL's, we actually
  531. ; rename this routine with an extra underscore with 'C' calling conventions
  532. ; and a small DLL stub will be provided by the high level code to call the
  533. ; assembler routine.
  534.  
  535. MACRO   procstartdll16 name      ; Set up DLL _export'ed proc
  536. ifdef    __WINDOWS16__
  537. procstartdll    _&name&
  538. else
  539. procstartdll    name
  540. endif
  541. ENDM
  542.  
  543. MACRO   procenddll16 name
  544. ifdef    __WINDOWS16__
  545. procend        _&name&
  546. else
  547. procend        name
  548. endif
  549. ENDM
  550.  
  551. MACRO   procstatic name         ; Set up model independant private proc
  552. if codesize
  553. PROC    name FAR
  554. else
  555. PROC    name NEAR
  556. endif
  557. ENDM
  558.  
  559. MACRO   procnear name           ; Set up near proc
  560. PROC    name NEAR               ; and export name
  561.         PUBLIC name
  562. ENDM
  563.  
  564. MACRO   procfar name            ; Set up far proc
  565. PROC    name FAR                ; and export name
  566.         PUBLIC name
  567. ENDM
  568.  
  569. MACRO   procend name            ; End procedure macro
  570. ENDP    name
  571. ENDM
  572.  
  573. ; Macros for the _DATA data segment. This segment contains initialised data.
  574.  
  575. MACRO   begdataseg name
  576. ifdef   __FLAT__
  577.         DATASEG
  578. else
  579. if flatmodel
  580. SEGMENT _DATA DWORD PUBLIC USE32 'DATA'
  581. else
  582. SEGMENT _DATA WORD PUBLIC 'DATA'
  583. endif
  584. endif
  585. ENDM
  586.  
  587. MACRO   enddataseg name
  588. ifndef  __FLAT__
  589. ENDS    _DATA
  590. endif
  591. ENDM
  592.  
  593. MACRO   procstart32 name        ; Set up hybrid 16/32 proc
  594. ifdef   __WINDOWS16__            ; and export name
  595. ; For the hybrid 16/32 bit memory model, the function is actually FAR,
  596. ; but because the segment is marked as USE32, TASM assumes a 32 bit
  597. ; calling convention, which causes the ARG directives to be off by 2
  598. ; bytes. To fix this we make the far functions 32 bit NEAR, so that the
  599. ; return stack frame is 4 bytes not 6 bytes for a 32 bit FAR function.
  600. ; To return from a hybrid 16/32 function you must use the ret32 macro
  601. ; rather than issuing a normal ret instruction.
  602. PROC    name NEAR
  603.         PUBLICDLL name
  604. else
  605. if codesize
  606. PROC    name FAR
  607.         PUBLIC name
  608. else
  609. PROC    name NEAR
  610.         PUBLIC name
  611. endif
  612. endif
  613. ENDM
  614.  
  615. ; Macros for the _BSS data segment. This segment contains initialised data.
  616.  
  617. MACRO   begbssseg name
  618. ifdef   __FLAT__
  619.         DATASEG
  620. else
  621. if flatmodel
  622. SEGMENT _BSS DWORD PUBLIC USE32 'BSS'
  623. else
  624. SEGMENT _BSS WORD PUBLIC 'BSS'
  625. endif
  626. endif
  627. ENDM
  628.  
  629. MACRO   endbssseg name
  630. ifndef  __FLAT__
  631. ENDS    _BSS
  632. endif
  633. ENDM
  634.  
  635. ; Macro to be invoked at the start of all modules to set up segments for
  636. ; later use.
  637.  
  638. MACRO   header name
  639. begdataseg name
  640. enddataseg name
  641. begbssseg  name
  642. endbssseg  name
  643. ENDM
  644.  
  645. ; Macro for the main code segment.
  646.  
  647. MACRO   begcodeseg name
  648. ifdef   __FLAT__
  649.         CODESEG
  650.         ASSUME  CS:FLAT,DS:FLAT,SS:FLAT
  651. else
  652. if flatmodel
  653. SEGMENT _TEXT DWORD PUBLIC USE32 'CODE'
  654. GROUP   DGROUP _DATA,_BSS
  655.         ASSUME  CS:_TEXT,DS:DGROUP
  656. else
  657. SEGMENT &name&_TEXT BYTE PUBLIC USE16 'CODE'
  658. GROUP   DGROUP _DATA,_BSS
  659.         ASSUME CS:&name&_TEXT,DS:DGROUP
  660. endif
  661. endif
  662. ENDM
  663.  
  664. MACRO   endcodeseg name
  665. ifndef  __FLAT__
  666. if flatmodel
  667. ENDS    _TEXT
  668. else
  669. ENDS    &name&_TEXT
  670. endif
  671. endif
  672. ENDM
  673.  
  674. ; Macro to begin a 32 bit code segment. For 32 bit protected mode this is
  675. ; no different to a normal FLAT mode code segment. For 16 bit protected mode,
  676. ; this is a USE32 code segment, with 16 bit calling conventions. The code
  677. ; itself is assembled as full 32 bit code, but the stack is 16 bit and
  678. ; the functions are 16 bit far functions. This allows the code full access
  679. ; to 4Gb from the start of a data segment, so we can get full access to
  680. ; large memory blocks from 16 bit PM without needing to resort to horrid
  681. ; selector/offset manipulation. This does of course require a 386 or higher
  682. ; processor! Note also that you _CANNOT_ link this USE32 code with other
  683. ; USE16 code segments. You should put all your 32 bit code in one hybrid
  684. ; segment if possible - maximum of 64k in each of course. If you have
  685. ; more than one segment, you will need to declare and call multiple
  686. ; ??_enable32() functions to convert the segments to 32 bit hyrbid code
  687. ; under Windows DPMI.
  688.  
  689. MACRO   begcodeseg32 name
  690. ifdef   __WINDOWS16__
  691. SEGMENT &name&_TEXT32 DWORD PUBLIC USE32 'CODE'
  692. GROUP   DGROUP _DATA,_BSS
  693.         ASSUME CS:&name&_TEXT32,DS:DGROUP
  694. else
  695. begcodeseg    name
  696. endif
  697. ENDM
  698.  
  699. MACRO   endcodeseg32 name
  700. ifdef   __WINDOWS16__
  701. ENDS    &name&_TEXT32
  702. else
  703. endcodeseg    name
  704. endif
  705. ENDM
  706.  
  707. ; Macro to return from a 32 bit routine to the native protected mode
  708. ; environment. In 16 bit PM this does a 16:16 far return to the original
  709. ; 16 bit code. Under 32 bit PM this will be a 32 bit near return.
  710.  
  711. MACRO    ret32
  712. ifdef   __WINDOWS16__
  713.         db 066h,0CBh
  714. else
  715.         ret
  716. endif
  717. ENDM
  718.  
  719. ; Macro to create a routine to convert the CS selector for the segment from
  720. ; a 16 bit selector to a 32 bit selector. We do this by checking if we
  721. ; are running 16 or 32 bit code, if we are running 16 bit code we convert
  722. ; the selector to 32 bit (the code currently requires DPMI for this, but
  723. ; we only support Borland's DPMI16 and Windows DPMI for 16 bit PM code
  724. ; anyway). This code comes courtesy of the 32 bit hacked CMACROS.INC
  725. ; in the Microsoft WinG Software Development Kit.
  726. ;
  727. ; Note that you will need to explicitly call this function before accessing
  728. ; any 32 bit code in each separate 32 bit segment that you have created.
  729.  
  730. MACRO   define_enable32 name
  731. ifdef   __WINDOWS16__
  732. &name&_fix_cs:
  733.         db 057h                     ; push    di
  734.         db 083h,0ECh,008h           ; sub     sp,8
  735.         db 08Ch,0CBh                ; mov     bx,cs
  736.         db 08Ch,0D0h                ; mov     ax,ss
  737.         db 08Eh,0C0h                ; mov     es,ax
  738.         db 08Bh,0FCh                ; mov     di,sp
  739.         db 0B8h,00Bh,000h           ; mov     ax,000Bh
  740.         db 0CDh,031h                ; int     31h
  741.         db 026h,080h,04Dh,006h,040h ; or      byte ptr es:[di+6],40h
  742.         db 0B8h,00Ch,000h           ; mov     ax,000Ch
  743.         db 0CDh,031h                ; int     31h
  744.         add     sp,8                ; db 083h,0C4h,008h
  745.         pop     di                  ; db 05Fh
  746. procfar        &name&_enable32
  747.         xor        eax,eax
  748.         mov        ah,80h
  749.         add        eax,eax
  750.         jc        short &name&_fix_cs
  751.         db 066h,0CBh                ; 16:16 retf
  752. procend        &name&_enable32
  753. endif
  754. ENDM
  755.  
  756. ; Boolean truth values (same as those in debug.h)
  757.  
  758. False        =    0
  759. True        =    1
  760. No            =    0
  761. Yes            =    1
  762.