msgmacro.inc

来自「用于查询PC机上的USB端口是否有设备挂接上」· INC 代码 · 共 553 行 · 第 1/2 页

INC
553
字号
	movzx   reg, @MSG_&c&AB.@msgab_rgOfs[msgno*2-2-2*@MSG_&c&CLASSMASK] ; Y: Get offset
	add     reg, @MSG_&c&AB.@msgab_pMsgs            ;    Add bias
	jmp     l                                       ;    Done
      skip:
    ENDIF
ENDM

; @MSG_GetOneConstClass: Internal helper macro for GET_MESSAGE_PTR
;
;   c = message class to try
;   msgnum = constant message number
;   reg = target register
;   @MSG_regstr = optional `+reg*2'

@MSG_GetOneConstClass MACRO c, msgnum, reg
    IF (msgnum AND @MSG_CLASSMASK) EQ @MSG_&c&CLASSMASK
%       movzx   reg, @MSG_&c&AB.@msgab_rgOfs[(msgnum AND @MSG_MSGMASK)*2-2 @MSG_regstr]
	add     reg, @MSG_&c&AB.@msgab_pMsgs            ; Add bias
    ENDIF
ENDM

;
; GET_MESSAGE_PTR msgnum, reg, msgreg
;
;   msgnum is the message number to retrieve, which can be a message constant
;   or a register.  Using a register is discouraged, however, because it
;   causes bloated code to be generated.
;
;   reg is the register to receive the result.
;
;   msgreg (optional) is a register which will be added to msgnum to produce
;   the actual message number.  If you want to pass a variable as msgnum,
;   you should instead pass a constant as msgnum and the offset from msgnum
;   as the msgreg.
;
; Valid input
;
;   GET_MESSAGE_PTR MSG_X, esi          - returns pointer to message X
;   GET_MESSAGE_PTR MSG_X, esi, eax     - returns pointer to message X+EAX
;   GET_MESSAGE_PTR eax,   esi          - returns pointer to message EAX
;                                         (larger than others)

GET_MESSAGE_PTR MACRO   msgnum:REQ, reg:REQ, msgreg
    LOCAL Done

    IF (OPATTR(msgnum)) AND 010h ; if msg number is in a register with no hint
	% forc c, @MSG_CLASSNAMES
		@MSG_GetOneRegClass c, msgnum, reg, Done
	endm
      Done:
    ELSE                        ; We have a hint; exploit it!
	IFB <msgreg>
		@MSG_regstr TEXTEQU <>
	ELSE
		@MSG_regstr TEXTEQU <+&msgreg*2>
	ENDIF

	% forc c, @MSG_CLASSNAMES
	     @MSG_GetOneConstClass c, <msgnum>, reg
	endm
    ENDIF
ENDM

;==============================================================================
;
; Macros for sprintf'ing messages
;
;==============================================================================

; @MSG_Lsprintf_Helper: Internal helper macro for LOCALIZED_SPRINTF
;
;   c = message class to try
;   msgnum = constant message number

@MSG_Lsprintf_Helper MACRO c, msgnum
    IF (msgnum AND @MSG_CLASSMASK) EQ @MSG_&c&CLASSMASK
	@MSG_callparams EQU <offset32 @MSG_&c&AB>
    ENDIF
ENDM

;
; LOCALIZED_SPRINTF
;
;   Usage:  LOCALIZED_SPRINTF buf, msgno, parms
;
;           buf   = where to put the output string
;           msgno = message number (must be a constant)
;           parms = optional parameters to the sprintf
;
;
;   Returns: None
;
;   Uses:   Flags

LOCALIZED_SPRINTF MACRO buf:REQ, msgnum:REQ, parms:VARARG

	@MSG_callparams textequ <ERROR: Bad message number>
	% forc c, @MSG_CLASSNAMES
	     @MSG_Lsprintf_Helper c, <msgnum>
	endm

	@MSG_callparams CATSTR <buf, >, @MSG_callparams, <, (msgnum) AND @MSG_MSGMASK, >, <parms>
	VMMCall _LocalizeSprintf, <%@MSG_callparams>

ENDM

;
; PUSH_SPRINTF
;
;   Usage:  PUSH_SPRINTF msgno, parms
;
;           msgno = message number
;           parms = optional parameters to the sprintf
;
;   The message number may be a constant (in which case it can be a
;   message from any class), or it may be held in a register (in
;   which case it *MUST* be a message ordinal from the LOCKED message
;   class).
;
;   If you want to pass a message number in a register, and the message
;   number is *NOT* for a locked message, then you must call one of the
;   PUSH_XXX_SPRINTF macros, such as PUSH_INIT_SPRINTF.
;
;   Returns: EAX -> output buffer (allocated from the stack)
;
;   Uses:   EAX, ESP, Flags
;
;   WARNING!  This services changes ESP by an unpredictable amount.
;   Any ESP-based parameters and/or local variables will be inaccessible
;   until you do a POP_SPRINTF.

PUSH_SPRINTF MACRO msgnum:REQ, params:VARARG

	@MSG_numvars = 2

  IFNB <params>
    FOR i, <params>
	@MSG_numvars = @MSG_numvars + 1
    ENDM
  ENDIF
  @MSG_numvarbyteshi = (@MSG_numvars*4) SHL 16

  IF (OPATTR(msgnum)) AND 010h        ; if msg number is in a register
	add     msgnum, @MSG_numvarbyteshi
	@MSG_callparams CATSTR <offset32 @MSG_LAB, msgnum, >, <params>
  ELSE
    @MSG_callparams textequ <ERROR: Bad message number>
    % forc c, @MSG_CLASSNAMES
	 @MSG_Lsprintf_Helper c, <msgnum>
    endm
    @MSG_callparams CATSTR @MSG_callparams, \
		    <, @MSG_numvarbyteshi + (msgnum AND @MSG_MSGMASK), >, <params>
  ENDIF

      @MSG_PushCParams <%@MSG_callparams>
      VMMCall _LocalizeStackSprintf

ENDM


;
; @MSG_PUSH_SPRINTF is a common worker for the PUSH_XXX_SPRINTF macros.
;

@MSG_PUSH_SPRINTF MACRO c:req, msgnum:REQ, params

	@MSG_numvars = 2
  IFNB <params>
    FOR i, <params>
	@MSG_numvars = @MSG_numvars + 1
    ENDM
  ENDIF
  @MSG_numvarbyteshi = (@MSG_numvars*4) SHL 16

  IF (OPATTR(msgnum)) AND 010h        ; if msg number is in a register
	add     msgnum, @MSG_numvarbyteshi-@MSG_&c&CLASSMASK
	@MSG_callparams CATSTR <offset32 @MSG_&c&AB, msgnum, >, <params>
  ELSE
      .erre (msgnum AND @MSG_CLASSMASK) EQ @MSG_&c&CLASSMASK
	@MSG_callparams CATSTR <offset32 @MSG_&c&AB, @MSG_numvarbyteshi + msgnum -@MSG_&c&CLASSMASK, >, <params>
  ENDIF
      @MSG_PushCParams <%@MSG_callparams>
      VMMCall _LocalizeStackSprintf

ENDM

;
; POP_SPRINTF
;
;   Usage:  POP_SPRINTF
;
;       This cleans the stack after a previous PUSH_SPRINTF or
;       PUSH_XXX_SPRINTF call.
;
;   Returns: None
;
;   Uses:   Flags

POP_SPRINTF MACRO
;BUGBUG add signature and assertion for debug
		add   esp, [esp]            ; Last item in block pushed is the size of the data block
		ENDM


PUSHED_SPRINTF_LENGTH MACRO reg:REQ
;BUGBUG add signature and assertion for debug
		mov   &reg, [esp+4]         ; Next to last item pushed is the length of the string
		ENDM


FATAL_ERROR_MSG MACRO MsgNum:REQ, ExitFlags
	GET_MESSAGE_PTR <&MsgNum>, esi
IFB <ExitFlags>
	xor     eax, eax
ELSE
	mov     eax, ExitFlags
ENDIF
	VMMcall Fatal_Error_Handler
	ENDM


FATAL_ERROR_SQZD_MSG MACRO MsgNum:REQ, ExitFlags
	PUSH_SPRINTF <&MsgNum>
	xchg    esi, eax
IFB <ExitFlags>
	xor     eax, eax
ELSE
	mov     eax, ExitFlags
ENDIF
	VMMcall Fatal_Error_Handler
	ENDM

;***    PushCParams
;
;       Processes argument list

@MSG_PushCParams macro arglst
	LOCAL   count
	LOCAL   count2

	count = 0                     ;; number of dwords on stack (global)
	FOR     x,<arglst>
		ifnb <x>
		    count = count + 1
		    @MSG_MakePush <x>,%count
		endif
	ENDM

	count2 = count
	REPEAT  count
		@MSG_DoPush <?AM>,%count2
		count2 = count2 - 1
	ENDM
	ENDM


; Makes a macro that will push argment when invoke - used by cCall only

@MSG_MakePush   macro   name, num
	.xcref
	.xcref  ?AM&num
	.cref
	?AM&num &macro
		push    name
		&endm
	endm
	.xcref  @MSG_MakePush

; Concatenates, invokes and purges a macro name - used by PushCParams

@MSG_DoPush macro   name1, name2
	name1&name2
	purge   name1&name2
	endm
	.xcref  @MSG_DoPush

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?