Hi,
I already posted this macro to the masm32forum, but haven't got any reply. Aditionally I know that these both sites visit different members, so I post it here too.
For some specific reason I need to assemble the CALL instruction myself using the following MASM macro "call2opcd".
I've tested this macro (with examples given in the code section) and it seems to be working well, but I appreciate your comments :)
There's a bunch of macros used by this macro, so if you want to compile this sample, download the package here: http://www.webpark.cz/mazegen/call2opcd_res.zip (4.5 KB), please (it seems that it is impossible to open this link directly from this site, so use cut&paste in new panel/window, it should work). It also contains the following asm source code file.
I already posted this macro to the masm32forum, but haven't got any reply. Aditionally I know that these both sites visit different members, so I post it here too.
For some specific reason I need to assemble the CALL instruction myself using the following MASM macro "call2opcd".
I've tested this macro (with examples given in the code section) and it seems to be working well, but I appreciate your comments :)
There's a bunch of macros used by this macro, so if you want to compile this sample, download the package here: http://www.webpark.cz/mazegen/call2opcd_res.zip (4.5 KB), please (it seems that it is impossible to open this link directly from this site, so use cut&paste in new panel/window, it should work). It also contains the following asm source code file.
; assumptions:
; o memory-access size is always 32 bits (i.e. CALL AX returns compile-time error)
; - if the operand size is 32-bit, it is therefore near call
; o if the argument references undefined symbol, it is either an user error or
; a forward-referenced label: macro always assumes it is the label
call2opcd MACRO arg:VARARG
local arg
local curreip ;; current EIP to fix relative offset
local start, end
local pos, tmp
IF @InStr (, <arg>, <,>)
ErrorEcho <"call &arg" instruction, call2opcd macro>, <too many arguments to call: arg>
EXITM
ENDIF
IF @InStr (, arg, <$>) ;; label relative to EIP? (e.g. CALL $+5)
BYTE 0E8H ;; relative direct call
DWORD arg - 1 - curreip ;; minus 1 byte
ELSE
IFE $IsNoError (arg) ;; is it an user error or a forward-referenced label?
BYTE 0E8H ;; always assume it is forward-referenced label
DWORD arg - curreip
ELSE
IF $IsCodeLabel (arg) ;; is it backward-referenced label?
BYTE 0E8H ;; relative direct call
DWORD arg - curreip
ELSE ;; it is indirect call
IF $IsReg (arg)
IFE ($IsGeneralReg (arg)) AND ($GetSizeOf (arg) GT TYPE BYTE)
ErrorEcho <"call &arg" instruction, call2opcd macro>, <invalid operand : arg>
EXITM
ENDIF
IF TYPE (arg) NE TYPE DWORD
ErrorEcho <"call &arg" instruction, call2opcd macro>, <only DWORD operand supported : arg>
EXITM
ENDIF
start:
not arg ;; assemble needed opcode extension 010
end:
ORG start
BYTE 0FFH ;; make call near
ORG end
ELSE ;; it is indirect call, address given in memory
IF TYPE (arg) EQ TYPE BYTE
ErrorEcho <"call &arg" instruction, call2opcd macro>, <invalid operand : arg>
EXITM
ENDIF
IFE (TYPE (arg) EQ TYPE DWORD) OR (TYPE (arg) EQ TYPE FWORD)
ErrorEcho <"call &arg" instruction, call2opcd macro>, \
<only DWORD or FWORD operand supported : arg>
EXITM
ENDIF
start:
IF TYPE (arg) EQ TYPE DWORD
;; if 32-bit operand, always assume it is near call
not arg ;; assemble needed opcode extension 010
ELSE
;; else it is far call: always add "dword ptr" because of NEG instr
pos INSTR $lcase (arg), <ptr> ;; is there any "ptr" already?
IF pos ;; yea, replace this whole string
tmp CATSTR <dword ptr>, @SubStr (arg, pos + @SizeStr (<ptr>))
ELSE
tmp CATSTR <dword ptr>, <arg>
ENDIF
neg tmp ;; assemble needed opcode extension 011
ENDIF
end:
ORG start
BYTE 0FFH ;; make call
ORG end
ENDIF
ENDIF
ENDIF
ENDIF
curreip = $
ENDM
.DATA
neartarget DWORD ?
fartarget FWORD ?
.CODE
Start:
; tests:
call $+5
call2opcd $+5 ; explicit EIP-relative call to next instruction
nop
call somelabel
call2opcd somelabel ; forward-referenced label, relative call
nop
call Start
call2opcd Start ; backward-referenced label, relative call
nop
call edi
call2opcd edi ; absolute indirect near call, address given in register
nop
call [neartarget]
call2opcd [neartarget] ; absolute indirect near call, address given in memory
nop
call [fartarget]
call2opcd [fartarget] ; absolute indirect far call, address given in memory
nop
call dword ptr [edi]
call2opcd dword ptr [edi] ; absolute indirect near call, address given in memory
nop
call fword ptr [edi]
call2opcd fword ptr [edi] ; absolute indirect far call, address given in memory
somelabel:
; error-trapping tests:
; call2opcd Start, somelabel
; call2opcd al
; call2opcd cs
; call2opcd byte ptr [eax]
; call2opcd word ptr [eax]
END Start