Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1197 lines
19 KiB

  1. ;
  2. ; Microsoft Confidential
  3. ; Copyright (C) Microsoft Corporation 1991
  4. ; All Rights Reserved.
  5. ;
  6. ;** Macro definitions for MSDOS.
  7. ;
  8. ; Revision history:
  9. ; M019 DB 10/26/90 - Added Cmp32 macro.
  10. TRUE EQU 0FFFFh
  11. FALSE EQU 0
  12. SUBTTL BREAK a listing into pages and give new subtitles
  13. PAGE
  14. BREAK MACRO subtitle
  15. SUBTTL subtitle
  16. PAGE
  17. ENDM
  18. .xcref break
  19. BREAK <ASMVAR - handle assembly variables once and for all>
  20. AsmVars Macro varlist
  21. IRP var,<varlist>
  22. AsmVar var
  23. ENDM
  24. ENDM
  25. AsmVar Macro var
  26. IFNDEF var
  27. var = FALSE
  28. ENDIF
  29. ENDM
  30. BREAK <I_NEED: declare a variable external, if necessary, and allocate a size>
  31. ;
  32. ; declare a variable external and allocate a size
  33. ;
  34. AsmVar InstalledData
  35. I_NEED MACRO sym,len
  36. IF NOT InstalledData
  37. DOSDATA SEGMENT WORD PUBLIC 'DATA'
  38. IFIDN <len>,<WORD>
  39. EXTRN &sym:WORD
  40. ELSE
  41. IFIDN <len>,<DWORD>
  42. EXTRN &sym:DWORD
  43. ELSE
  44. EXTRN &sym:BYTE
  45. ENDIF
  46. ENDIF
  47. DOSDATA ENDS
  48. ENDIF
  49. ENDM
  50. .xcref I_need
  51. ; call a procedure that may be external. The call will be short.
  52. invoke MACRO name
  53. .xcref
  54. IF2
  55. IFNDEF name
  56. EXTRN name:NEAR
  57. ENDIF
  58. ENDIF
  59. .cref
  60. CALL name
  61. ENDM
  62. .xcref invoke
  63. PAGE
  64. ;
  65. ; jump to a label that may be external. The jump will be near.
  66. ;
  67. transfer MACRO name
  68. .xcref
  69. IF2
  70. IFNDEF name
  71. EXTRN name:NEAR
  72. ENDIF
  73. ENDIF
  74. .cref
  75. JUMP name
  76. ENDM
  77. .xcref transfer
  78. ;
  79. ; get a short address in a word
  80. ;
  81. short_addr MACRO name
  82. IFDIF <name>,<?>
  83. .xcref
  84. IF2
  85. IFNDEF name
  86. EXTRN name:NEAR
  87. ENDIF
  88. ENDIF
  89. .cref
  90. DW OFFSET DOSCODE:name
  91. ELSE
  92. DW ?
  93. ENDIF
  94. ENDM
  95. .xcref short_addr
  96. ;
  97. ; get a long address in a dword
  98. ;
  99. long_addr MACRO name
  100. .xcref
  101. IF2
  102. IFNDEF name
  103. EXTRN name:NEAR
  104. ENDIF
  105. ENDIF
  106. .cref
  107. DD name
  108. ENDM
  109. .xcref long_addr
  110. ;
  111. ; declare a PROC near or far but PUBLIC nonetheless
  112. ;
  113. .xcref ?frame
  114. .xcref ?aframe
  115. .xcref ?stackdepth
  116. .xcref ?initstack
  117. ?frame = 0 ; initial
  118. ?aframe = 0 ; initial
  119. ?stackdepth = 0 ; initial stack size
  120. ?initstack = 0 ; initial stack size
  121. procedure MACRO name,distance
  122. ?frame = 0
  123. ?aframe = 2 ;; remember the pushed BP
  124. PUBLIC name
  125. name PROC distance
  126. ASSUME DS:nothing,ES:nothing
  127. ?initstack = ?stackdepth ;; beginning of procedure
  128. ENDM
  129. .xcref procedure
  130. ; end a procedure and check that stack depth is preserved
  131. EndProc MACRO name, chk
  132. IFDIF <chk>,<NoCheck> ;; check the stack size
  133. IF2
  134. IF ?initstack NE ?stackdepth ;; is it different?
  135. %OUT ***** Possible stack size error in name *****
  136. ENDIF
  137. ENDIF
  138. ENDIF
  139. name ENDP
  140. ENDM
  141. .xcref endproc
  142. PAGE
  143. ;
  144. ; define a data item to be public and of an appropriate size/type
  145. ;
  146. I_AM MACRO name,size,init
  147. ;; declare the object public
  148. PUBLIC name
  149. ;; declare the type of the object
  150. IFIDN <size>,<WORD>
  151. name LABEL WORD
  152. I_AM_SIZE = 1
  153. I_AM_LEN = 2
  154. ELSE
  155. IFIDN <size>,<DWORD>
  156. name LABEL DWORD
  157. I_AM_SIZE = 2
  158. I_AM_LEN = 2
  159. ELSE
  160. IFIDN <size>,<BYTE>
  161. name LABEL BYTE
  162. I_AM_SIZE = 1
  163. I_AM_LEN = 1
  164. ELSE
  165. name LABEL BYTE
  166. I_AM_SIZE = size
  167. I_AM_LEN = 1
  168. ENDIF
  169. ENDIF
  170. ENDIF
  171. ;; if no initialize then allocate blank storage
  172. IFB <init>
  173. DB I_AM_SIZE*I_AM_LEN DUP (?)
  174. ELSE
  175. IF NOT InstalledData
  176. IRP itm,<init>
  177. IF I_AM_LEN EQ 1
  178. DB itm
  179. ELSE
  180. DW itm
  181. ENDIF
  182. I_AM_SIZE = I_AM_SIZE - 1
  183. ENDM
  184. IF I_AM_SIZE NE 0
  185. %out ***** initialization of name not complete *****
  186. ENDIF
  187. ELSE
  188. DB I_AM_SIZE*I_AM_LEN DUP (?)
  189. ENDIF
  190. ENDIF
  191. ENDM
  192. .xcref I_AM
  193. .xcref I_AM_SIZE
  194. .xcref I_AM_LEN
  195. I_AM_SIZE = 0
  196. I_AM_LEN = 0
  197. PAGE
  198. ;
  199. ; define an entry in a procedure
  200. ;
  201. entry macro name
  202. PUBLIC name
  203. name:
  204. endm
  205. .xcref entry
  206. BREAK <ERROR - store an error code then jump to a label>
  207. error macro code
  208. .xcref
  209. MOV AL,code
  210. transfer SYS_RET_ERR
  211. .cref
  212. ENDM
  213. .xcref error
  214. BREAK <JUMP - real jump that links up shortwise>
  215. ;
  216. ; given a label <lbl> either 2 byte jump to another label <lbl>_J
  217. ; if it is near enough or 3 byte jump to <lbl>
  218. ;
  219. jump macro lbl
  220. local a
  221. .xcref
  222. ifndef lbl&_J ;; is this the first invocation
  223. a: JMP lbl
  224. ELSE
  225. IF (lbl&_J GE $) OR ($-lbl&_J GT 126)
  226. a: JMP lbl ;; is the jump too far away?
  227. ELSE
  228. a: JMP lbl&_J ;; do the short one...
  229. ENDIF
  230. ENDIF
  231. lbl&_j = a
  232. .cref
  233. endm
  234. .xcref jump
  235. BREAK <RETURN - return from a function>
  236. return macro x
  237. local a
  238. .xcref
  239. a:
  240. RET
  241. ret_l = a
  242. .cref
  243. endm
  244. .xcref return
  245. BREAK <CONDRET - conditional return>
  246. condret macro cc,ncc
  247. local a
  248. .xcref
  249. .xcref a
  250. .cref
  251. ifdef ret_l ;; if ret_l is defined
  252. if (($ - ret_l) le 126) and ($ gt ret_l)
  253. ;; if ret_l is near enough then
  254. a: j&cc ret_l ;; a: j<CC> to ret_l
  255. ret_&cc = a ;; define ret_<CC> to be a:
  256. exitm
  257. endif
  258. endif
  259. ifdef ret_&cc ;; if ret_<CC> defined
  260. if (($ - ret_&cc) le 126) and ($ gt ret_&cc)
  261. ;; if ret_<CC> is near enough
  262. a: j&cc ret_&cc ;; a: j<CC> to ret_<CC>
  263. ret_&cc = a ;; define ret_<CC> to be a:
  264. exitm
  265. endif
  266. endif
  267. j&ncc a ;; j<NCC> a:
  268. return ;; return
  269. a: ;; a:
  270. ret_&cc = ret_l ;; define ret_<CC> to be ret_l
  271. endm
  272. .xcref condret
  273. BREAK <RETZ - return if zero, links up shortwise if necessary>
  274. retz macro
  275. condret z,nz
  276. endm
  277. .xcref retz
  278. BREAK <RETNZ - return if not zero, links up shortwise if necessary>
  279. retnz macro
  280. condret nz,z
  281. endm
  282. .xcref retnz
  283. BREAK <RETC - return if carry set, links up shortwise if necessary>
  284. retc macro
  285. condret c,nc
  286. endm
  287. .xcref retc
  288. BREAK <RETNC - return if not carry, links up shortwise if necessary>
  289. retnc macro
  290. condret nc,c
  291. endm
  292. .xcref retnc
  293. BREAK <CONTEXT - set the DOS context to a particular register>
  294. context macro r
  295. PUSH SS
  296. POP r
  297. ASSUME r:DOSDATA
  298. endm
  299. .xcref context
  300. BREAK <SaveReg - save a set of registers>
  301. SaveReg MACRO reglist ;; push those registers
  302. IRP reg,<reglist>
  303. ?stackdepth = ?stackdepth + 1
  304. PUSH reg
  305. ENDM
  306. ENDM
  307. .xcref SaveReg
  308. Save MACRO arglist ;; push those arguments
  309. IRP arg,<arglist>
  310. ?stackdepth = ?stackdepth + 1
  311. PUSH arg
  312. ENDM
  313. ENDM
  314. .xcref Save
  315. BREAK <RestoreReg - unsave some registers>
  316. RestoreReg MACRO reglist ;; pop those registers
  317. IRP reg,<reglist>
  318. ?stackdepth = ?stackdepth - 1
  319. POP reg
  320. ENDM
  321. ENDM
  322. .xcref RestoreReg
  323. Restore MACRO arglist ;; pop those arguments
  324. IRP arg,<arglist>
  325. ?stackdepth = ?stackdepth - 1
  326. POP arg
  327. ENDM
  328. ENDM
  329. .xcref Restore
  330. BREAK <Critical section macros>
  331. EnterCrit MACRO section
  332. ; Invoke E&section
  333. ENDM
  334. LeaveCrit MACRO section
  335. ; Invoke L&section
  336. ENDM
  337. Break <message - display a message>
  338. AsmVars <ShareF,Cargs,Redirector>
  339. if debug
  340. fmt MACRO typ,lev,fmts,args
  341. local a,b,c
  342. PUSHF
  343. IFNB <typ>
  344. TEST BugTyp,typ
  345. JZ c
  346. CMP BugLev,lev
  347. JB c
  348. ENDIF
  349. PUSH AX
  350. PUSH BP
  351. MOV BP,SP
  352. If (not sharef) and (not redirector)
  353. DOSDATA segment
  354. a db fmts,0
  355. DOSDATA ends
  356. MOV AX,OFFSET DOSDATA:a
  357. else
  358. jmp short b
  359. a db fmts,0
  360. if sharef
  361. b: mov ax,offset share:a
  362. else
  363. b: mov ax,offset netwrk:a
  364. endif
  365. endif
  366. PUSH AX
  367. cargs = 2
  368. IRP item,<args>
  369. IFIDN <AX>,<item>
  370. push [bp+2]
  371. ; MOV AX,[BP+2]
  372. ELSE
  373. ; MOV AX,item
  374. push item
  375. ENDIF
  376. ; PUSH AX
  377. cargs = cargs + 2
  378. ENDM
  379. invoke PFMT
  380. ADD SP,Cargs
  381. POP BP
  382. POP AX
  383. c:
  384. POPF
  385. ENDM
  386. else
  387. fmt macro
  388. endm
  389. endif
  390. Break <DOSAssume - validate assumes>
  391. AsmVar Debug,$temp
  392. ;** DOSAssume - Check that a register addresses DOSSEG
  393. ;
  394. ; DOSAssume reglist, message
  395. IF debug
  396. DOSAssume Macro reglist,message
  397. local a,b
  398. $temp = 0
  399. IRP r,<reglist>
  400. IFIDN <r>,<DS>
  401. $temp = $temp OR 2
  402. ELSE
  403. IFIDN <r>,<ES>
  404. $temp = $temp OR 4
  405. ELSE
  406. IFIDN <r>,<SS>
  407. $temp = $temp OR 1
  408. ELSE
  409. %out ***** Invalid register reg in DOSAssume *****
  410. ENDIF
  411. ENDIF
  412. ENDIF
  413. ENDM
  414. Invoke SegCheck
  415. jmp short a
  416. db $temp
  417. db message,0
  418. a:
  419. IRP r,<reglist>
  420. ASSUME r:DOSDATA
  421. ENDM
  422. ENDM
  423. ELSE
  424. DOSAssume Macro reglist,message
  425. IRP r,<reglist>
  426. ASSUME r:DOSDATA
  427. ENDM
  428. ENDM
  429. ENDIF
  430. BREAK <ASSERT - make assertions about registers>
  431. IF DEBUG
  432. Assert MACRO kind, objs, message
  433. LOCAL a,b
  434. IFIDN <kind>,<Z>
  435. CMP objs,0
  436. JZ a
  437. fmt <>,<>,<message>
  438. a:
  439. ELSE
  440. IFIDN <kind>,<NZ>
  441. CMP objs,0
  442. JNZ a
  443. fmt <>,<>,<message>
  444. a:
  445. ELSE
  446. PUSH AX
  447. IRP obj,<objs>
  448. PUSH obj
  449. ENDM
  450. IF SHAREF
  451. MOV AX,OFFSET b
  452. ELSE
  453. MOV AX,OFFSET DOSDATA:b
  454. ENDIF
  455. PUSH AX
  456. IFIDN <kind>,<ISBUF>
  457. Invoke BUFCheck
  458. ENDIF
  459. IFIDN <kind>,<ISSFT>
  460. Invoke SFTCheck
  461. ENDIF
  462. IFIDN <kind>,<ISDPB>
  463. Invoke DPBCheck
  464. ENDIF
  465. POP AX
  466. IF SHAREF
  467. JMP SHORT a
  468. b DB Message,0
  469. a:
  470. ELSE
  471. DOSDATA segment
  472. b db Message,0
  473. DOSDATA ends
  474. ENDIF
  475. ENDIF
  476. ENDIF
  477. ENDM
  478. ELSE
  479. Assert Macro
  480. ENDM
  481. ENDIF
  482. Break <CallInstall - hook to installable pieces>
  483. CallInstall MACRO name,mpx,fn,save,restore
  484. IF Installed
  485. IFNB <save>
  486. SaveReg <save>
  487. ENDIF
  488. MOV AX,(mpx SHL 8) + fn
  489. INT 2Fh
  490. IFNB <restore>
  491. RestoreReg <restore>
  492. ENDIF
  493. ELSE
  494. Invoke name
  495. ENDIF
  496. ENDM
  497. Break <Stack frame manipulators>
  498. localvar macro name,length
  499. local a
  500. ifidn <length>,<BYTE>
  501. ?frame = ?frame + 1
  502. a = ?frame
  503. name EQU BYTE PTR [BP-a]
  504. else
  505. ifidn <length>,<WORD>
  506. ?frame = ?frame + 2
  507. a = ?frame
  508. name EQU WORD PTR [BP-a]
  509. else
  510. ifidn <length>,<DWORD>
  511. ?frame = ?frame + 4
  512. a = ?frame
  513. name EQU DWORD PTR [BP-a]
  514. name&l EQU WORD PTR [BP-a]
  515. name&h EQU WORD PTR [BP-a+2]
  516. else
  517. ?frame = ?frame + length
  518. a = ?frame
  519. name EQU BYTE PTR [BP-a]
  520. endif
  521. endif
  522. endif
  523. endm
  524. enter macro
  525. push bp
  526. mov bp,sp
  527. sub sp,?frame
  528. endm
  529. leave macro
  530. mov sp,bp
  531. pop bp
  532. endm
  533. Argvar macro name,length
  534. local a
  535. ifidn <length>,<BYTE>
  536. a = ?aframe
  537. ?aframe = ?aframe + 1
  538. name EQU BYTE PTR [BP+a]
  539. else
  540. ifidn <length>,<WORD>
  541. a = ?aframe
  542. ?aframe = ?aframe + 2
  543. name EQU WORD PTR [BP+a]
  544. else
  545. ifidn <length>,<DWORD>
  546. a = ?aframe
  547. ?aframe = ?aframe + 4
  548. name EQU DWORD PTR [BP+a]
  549. name&l EQU WORD PTR [BP+a]
  550. name&h EQU WORD PTR [BP+a+2]
  551. else
  552. a = ?aframe
  553. ?aframe = ?aframe + length
  554. name EQU BYTE PTR [BP+a]
  555. endif
  556. endif
  557. endif
  558. endm
  559. save_world macro
  560. push es
  561. invoke save_user_world
  562. endm
  563. restore_world macro
  564. invoke restore_user_world
  565. pop es
  566. endm
  567. ;
  568. ; This macro gets the DOS data segment value and puts it in the specified
  569. ; segment register. This can only be used in the DOSCODE segment.
  570. ;
  571. getdseg macro r
  572. mov r, cs:[DosDseg]
  573. assume r:dosdata
  574. endm
  575. ;
  576. ; This macro does the necessary extrns to allow use of the getdseg macro.
  577. ;
  578. allow_getdseg macro
  579. ifdef ROMDOS
  580. extrn BioDataSeg:word
  581. bdata segment at 70H
  582. extrn DosDataSg:word
  583. bdata ends
  584. else
  585. extrn DosDseg:word
  586. endif
  587. endm
  588. BREAK <LJcc - Long Conditional Jumps>
  589. LJE macro l
  590. LJ JE JNE l
  591. endm
  592. LJNE macro l
  593. LJ jne JE l
  594. endm
  595. LJZ macro l
  596. LJE l
  597. endm
  598. LJNZ macro l
  599. LJNE l
  600. endm
  601. LJC macro l
  602. LJ jc JNC l
  603. endm
  604. LJNC macro l
  605. LJ jnc JC l
  606. endm
  607. LJA macro l
  608. LJ ja JNA l
  609. endm
  610. LJNA macro l
  611. LJ jna JA l
  612. endm
  613. LJB macro l
  614. LJ jb JNB l
  615. endm
  616. LJNB macro l
  617. LJ jnb JB l
  618. endm
  619. LJS macro l
  620. LJ js JNS l
  621. endm
  622. LJNS macro l
  623. LJ jns JS l
  624. endm
  625. LJAE macro l
  626. LJ jae JNAE l
  627. endm
  628. LJBE macro l
  629. LJ jbe JNBE l
  630. endm
  631. LJL macro l
  632. LJ jl JNL l
  633. endm
  634. LJG macro l
  635. LJ jg JNG l
  636. endm
  637. LJLE macro l
  638. LJ jle JNLE l
  639. endm
  640. DLJE macro l
  641. DLJ JE JNE l
  642. endm
  643. DLJNE macro l
  644. DLJ jne JE l
  645. endm
  646. DLJZ macro l
  647. DLJE l
  648. endm
  649. DLJNZ macro l
  650. DLJNE l
  651. endm
  652. DLJC macro l
  653. DLJ jc JNC l
  654. endm
  655. DLJNC macro l
  656. DLJ jnc JC l
  657. endm
  658. DLJA macro l
  659. DLJ ja JNA l
  660. endm
  661. DLJNA macro l
  662. DLJ jna JA l
  663. endm
  664. DLJB macro l
  665. DLJ jb JNB l
  666. endm
  667. DLJNB macro l
  668. DLJ jnb JB l
  669. endm
  670. DLJS macro l
  671. DLJ js JNS l
  672. endm
  673. DLJNS macro l
  674. DLJ jns JS l
  675. endm
  676. DLJAE macro l
  677. DLJ jae JNAE l
  678. endm
  679. DLJBE macro l
  680. DLJ jbe JNBE l
  681. endm
  682. DLJG macro l
  683. DLJ jg JNG l
  684. endm
  685. DLJL macro l
  686. DLJ jl JNL l
  687. endm
  688. DLJLE macro l
  689. DLJ jle JNLE l
  690. endm
  691. ;* LJ - generate long conditional jump
  692. ;
  693. ; if target preceeds us and is in range just use a short jump
  694. ; else use a long jump
  695. ;
  696. ; LJ <direct jmp>,<skip jmp>,<label>
  697. LJ MACRO dirop,idirop,l
  698. local a
  699. IF ((.TYPE l) XOR 20h) AND 0A0h
  700. idirop a ;; not defined or is external
  701. jmp l
  702. a:
  703. ELSE ;; is local definied
  704. IF (($-l) LT 124) AND ($ GT l)
  705. dirop l ;; is before and within range
  706. ELSE
  707. idirop a ;; is out of range or forward (pass 2)
  708. jmp l
  709. a:
  710. ENDIF
  711. ENDIF
  712. ENDM
  713. ;* DLJ - generate debug long conditional jump
  714. ;
  715. ; If DEBUG is defined then we generate a long jump, else a short
  716. ; one.
  717. ;
  718. ; DLJ <direct jmp>,<skip jmp>,<label>
  719. DLJ MACRO dirop,idirop,l
  720. local a
  721. IF DEBUG
  722. idirop a
  723. jmp l
  724. a:
  725. ELSE
  726. dirop l
  727. ENDIF
  728. ENDM
  729. .xcref LJE, LJNE, LJZ, LJNZ, LJC, LJNC, LJA, LJNA
  730. .xcref LJB, LJNB, LJS, LJNS, LJAE, LJBE, LJG, LJL, LJLE
  731. .xcref DLJE, DLJNE, DLJZ, DLJNZ, DLJC, DLJNC, DLJA, DLJNA
  732. .xcref DLJB, DLJNB, DLJS, DLJNS, DLJAE, DLJBE, DLJG, DLJL, DLJLE
  733. .xcref LJ,DLJ
  734. ;** SHORT offset macro
  735. ;
  736. ; expands to SHORT if non debug, to nul if debug.
  737. ;
  738. ; this allows us to code
  739. ;
  740. ; jmp SHRT foobar
  741. ;
  742. ; and get a long form if debugging is turned on (because the extra
  743. ; debug code puts the target out of range)
  744. if DEBUG
  745. SHRT EQU <>
  746. else
  747. SHRT EQU SHORT
  748. endif
  749. ;** FALLTHRU - Verifies Fallthrough Validity
  750. FALLTHRU MACRO labl
  751. ; BUGBUG - restore align when we make code segment word aligned
  752. ; align 2 ; don't have errnz fail due to alignment
  753. IF2 ; of following label
  754. .errnz labl-$
  755. ENDIF
  756. ENDM
  757. ;** INTTEST - Generate an INT 3 for testing
  758. INTTEST MACRO
  759. if DEBUG
  760. int 3
  761. endif
  762. ENDM
  763. ;** DPUBLIC - Make a public symbol for debugging
  764. DPUBLIC MACRO arg
  765. if DEBUG
  766. public arg
  767. endif
  768. ENDM
  769. ;* Debug Traps
  770. ;
  771. ; These are removed as the code is exercised
  772. TRAP macro ; Like INTTEST but is normally left in during
  773. int 3 ; debugging; indicates "should not occur"
  774. ENDM
  775. TRAPC macro
  776. local l
  777. jnc short l
  778. int 3
  779. l:
  780. ENDM
  781. TRAPNC macro
  782. local l
  783. jc short l
  784. int 3
  785. l:
  786. ENDM
  787. TRAPA macro
  788. local l
  789. jna short l
  790. int 3
  791. l:
  792. ENDM
  793. TRAPNA macro
  794. local l
  795. ja short l
  796. int 3
  797. l:
  798. ENDM
  799. TRAPZ macro
  800. local l
  801. jnz short l
  802. int 3
  803. l:
  804. ENDM
  805. TRAPNZ macro
  806. local l
  807. jz short l
  808. int 3
  809. l:
  810. ENDM
  811. BREAK <Structure Field Macros>
  812. ;** Follows - Verify that a field follows another
  813. ;
  814. ; FOLLOWS field1, field2 [, size]
  815. ;
  816. ; This macro generates an error if "field1" doesn't immeidately
  817. ; follow "field2". If "size" is specified then an error is generated
  818. ; if Field1 is not of the proper size.
  819. FOLLOWS macro field1, field2, fldsiz
  820. .errnz field1 - size field2 - field2
  821. IFNB <fldsiz>
  822. .errnz size field1 - fldsiz
  823. ENDIF
  824. ENDM
  825. ;** LAST - Verify that a field is the last field in a structure
  826. ;
  827. ; LAST fieldname, structname
  828. ;
  829. ; Generates an error if fieldname is not last in structname.
  830. LAST macro fldnam, strunam
  831. .errnz size strunam - fldnam - size fldnam
  832. endm
  833. ;** TESTB - Use Byte form for Word TESTS, when possible
  834. ;
  835. ; TESTB is used in place of 16-bit TEST instructions. It substitutes
  836. ; a smaller 8-bit test when possible.
  837. TESTB macro targ,mask,thirdarg
  838. local mask2,delta
  839. ifnb <thirdarg>
  840. .err mask must be enclosed in brackets
  841. endif
  842. ifidn <targ>,<[bx]>
  843. test targ,mask
  844. exitm
  845. endif
  846. ifidn <targ>,<[si]>
  847. test targ,mask
  848. exitm
  849. endif
  850. ifidn <targ>,<[di]> ; don't process these operands specially
  851. test targ,mask
  852. exitm
  853. endif
  854. ifidn <targ>,<[BX]>
  855. test targ,mask
  856. exitm
  857. endif
  858. ifidn <targ>,<[SI]>
  859. test targ,mask
  860. exitm
  861. endif
  862. ifidn <targ>,<[DI]>
  863. test targ,mask
  864. exitm
  865. endif
  866. ifidn <targ>,<SI>
  867. test targ,mask
  868. exitm
  869. endif
  870. ifidn <targ>,<DI>
  871. test targ,mask
  872. exitm
  873. endif
  874. ifidn <targ>,<BP>
  875. test targ,mask
  876. exitm
  877. endif
  878. delta = 0
  879. mask2 = mask
  880. if mask2 AND 0ff00h
  881. ; have a mask bit in the high half
  882. if mask2 AND 0ffh
  883. test targ,mask
  884. exitm
  885. endif
  886. mask2 = mask2 SHR 8
  887. delta = 1
  888. endif
  889. ifidn <targ>,<AX>
  890. if delta
  891. test targ,mask
  892. else
  893. test AL,mask2
  894. endif
  895. exitm
  896. endif
  897. ifidn <targ>,<BX>
  898. if delta
  899. test BH,mask2
  900. else
  901. test BL,mask2
  902. endif
  903. exitm
  904. endif
  905. ifidn <targ>,<CX>
  906. if delta
  907. test CH,mask2
  908. else
  909. test CL,mask2
  910. endif
  911. exitm
  912. endif
  913. ifidn <targ>,<DX>
  914. if delta
  915. test DH,mask2
  916. else
  917. test DL,mask2
  918. endif
  919. exitm
  920. endif
  921. ifidn <targ>,<ax>
  922. if delta
  923. test targ,mask
  924. else
  925. test AL,mask2
  926. endif
  927. exitm
  928. endif
  929. ifidn <targ>,<bx>
  930. if delta
  931. test BH,mask2
  932. else
  933. test BL,mask2
  934. endif
  935. exitm
  936. endif
  937. ifidn <targ>,<cx>
  938. if delta
  939. test CH,mask2
  940. else
  941. test CL,mask2
  942. endif
  943. exitm
  944. endif
  945. ifidn <targ>,<dx>
  946. if delta
  947. test DH,mask2
  948. else
  949. test DL,mask2
  950. endif
  951. exitm
  952. endif
  953. test byte ptr targ+delta,mask2
  954. endm
  955. ;
  956. ; Some old versions of the 80286 have a bug in the chip. The popf
  957. ; instruction will enable interrupts. Therefore in a section of code with
  958. ; interrupts disabled and you need a popf instruction use the 'popff'
  959. ; macro instead.
  960. ;
  961. POPFF macro
  962. jmp $+3
  963. iret
  964. push cs
  965. call $-2
  966. endm
  967. Break <Cmp32 - 32-bit compare>
  968. ;----------------------------------------------------------------------------
  969. ;
  970. ; Macro Name : Cmp32
  971. ;
  972. ; Inputs:
  973. ; msw1 -- 1st operand, most significant word; MUST BE REGISTER.
  974. ; lsw1 -- 1st operand, least significant word; MUST BE REGISTER.
  975. ; msw2 -- 2nd operand, most significant word.
  976. ; lsw2 -- 2nd operand, least significant word.
  977. ; Function:
  978. ; Compare 2 32-bit operands. Implemented as a macro.
  979. ; Outputs:
  980. ; CF = 1 if 1st operand < 2nd operand
  981. ; = 0 if 1st operand >= 2nd operand
  982. ; ZF = 1 if 1st operand == 2nd operand
  983. ; = 0 if 1st operand <> 2nd operand
  984. ;-----------------------------------------------------------------------------
  985. ;M019: Created.
  986. Cmp32 MACRO msw1,lsw1,msw2,lsw2
  987. LOCAL cmp32x
  988. cmp msw1,msw2
  989. jne cmp32x
  990. cmp lsw1,lsw2
  991. cmp32x:
  992. ENDM
  993. Break <HRDSVC - SVC call where hard error is possible>
  994. ;----------------------------------------------------------------------------
  995. ;
  996. ; Macro Name : HRDSVC
  997. ;
  998. ; Inputs:
  999. ; iSVC -- SVC index
  1000. ; Function:
  1001. ; Make a DEM SVC. If hard error happens handle it.
  1002. ; Outputs:
  1003. ; CF = 1 if operation failed
  1004. ; = 0 if operation successful
  1005. ;-----------------------------------------------------------------------------
  1006. HRDSVC MACRO iSVC
  1007. LOCAL hs_nerr,hs_fail,hs_retry
  1008. SVC iSVC
  1009. jnc hs_nerr
  1010. ; Check if hard err to be handled . If no harderr then it
  1011. ; will come back without effecting any reg or carry flags.
  1012. ; Else it will do an int24. If user chooses retry it
  1013. ; will retry the SVC call. On fail or abort it will
  1014. ; come back with usual dos style setup.
  1015. ; If user chose "Abort" it wont come back
  1016. invoke TestHrdErr
  1017. hs_nerr:
  1018. ENDM
  1019.