最近我看着那些mmx寄存器一直没有得到利用. 心里实在是感觉过意不去了, 所以我写了一个宏, 利用mmx来传递参数. 我试验了一下比利用堆栈的stdcall, 要快一些, 而且程序结构也可以得到收获.
但是这个宏目前还有点问题, 这个宏在处理局部变量的时候使用的是textequ来定义. 方便我们使用宏的时候向原来的MASM高级伪指令PROC. 但是这样就遇到一个问题, textequ定义的宏在整个文件编译期间都是有效的, 显示局部变量的有效期只能够在变量生存期间有效.
所以我想请教下如何才能够取消textequ的原定义? 高手一定不要忘记指点. 还有一个问题. 如何判断一个宏参数是数值还是其他的东西. 这样在多加一层判断, 如果是寄存器参数直接传递到mmx寄存器.
如果是数值才用eax中转.写宏的时候可以更加高效. 目前还没有掌握如何才能够判断一个宏参数是否是数值. 是这样吗?
IF (OPATTR (arg)) AND 00000100b ;; TRUE表示是数值
搞定这两个问题基本就算比较完美了. 我把我写的宏也传递上来. 定义一个函数可以这样.
$Proc function1 uses ebx esi edi, _lpStr1:dword, _lpStr2:dword, _dwValue3:dword
local _dwValue1:dword
local _dwValue2:dword
movd eax, _lpStr1
movd ebx, _lpStr2
mov eax, _dwValue1
mov ecx, _dwValue2
ret
$Endp
使用起来也比较舒服吧, 这个和MASM的宏有个区别就是uese最后要以 逗号,结尾. 注意了. 还有function1和uses中间只能够使用空格, 不能够使用Tab, 这个bug我会修正. 调用可以这样
Jcall function1, offset Value1, addr Value2, ecx
使用eax是不允许的, 因为中间参数要使用eax作为中转, 我干脆禁止了使用eax, 调用也很舒服吧.. 参数有限制, 只有8个MMX寄存器. 所以参数最多8个.目前就是在参数那排定义的标号, 比如_lpStr1我内部是定义成 _lpStr1 textequ <mmx0>
问题就出在这里, 出了这个函数, 这个textequ还是有效. 有什么办法取消呢??
IfNdef __JoenCall__
__JoenCall__ = 1
_mov_ macro Index:req, SrcReg:req
local NewLine, Reg
Reg textequ <mm&Index>
NewLine textequ @CatStr( <movd >, %Reg, <,> <SrcReg> )
% NewLine
;% %out NewLine
endm
;============================================================================
;一种新的调用方式, 参数的传递方式从左边往右边开始传递, 和stdcall完全
;相反. 左边第一个参数放在mmx0中. 依次类推, 最多8个参数. 我给这种调用方式命名为
;Jcall目前调用支持的MASM操作符有addr offset 和寄存器, 但是eax不允许使用.
;主要是参数传递的时候eax要被重写. 容易出错. 所以我简单的判断了下. 不允许使用eax寄存器.
;但是不支持立即数,还有点问题.下面代码有注释..我没搞定这个..就是为了性能好点. 现在你可以这样调用函数
;不敢独享. 这个其实是参考了网上的.http://bbs.pediy.com/showthread.php?t=20938&highlight=opattr
;thebutterfly <让你的MASM支持__fastcall调用方式>
;Jcall function1, argv1, argv2, argv3, argv4, argv5, argv6, argv7, argv8
;============================================================================
Jcall macro _Proc:req, argList:vararg
local count, Reg
local arg, line, Flags
IfNb <argList> ;如果参数非空则汇编
count = 0
% for arg,< argList > ;判断参数个数是否超过8个
count = count + 1
If &count& GT 8
line textequ %@Line ;打印错误行号
% %out --> Eroor: Jcall parameter GE in the @FileCur(line) Line!
.Err
Endif
IfIDNI <arg>, <eax>
line textequ %@Line ;打印错误行号
% %out --> Eroor: Jcall eax register value overwritten by fastdcall @FileCur(line) Line!
.Err
Endif
Endm
count = 0
Flags = 1
% for arg,< argList > ;遍历所有参数然后压栈
count = count + 1
If @SizeStr( <arg> ) GE 6
;判断是否有offset操作符
IfIDNi @SubStr( <arg>, 1, 7 ), <offset >
mov eax,arg
_mov_ %count-1, eax ;这是直接压入内容
Flags = 0
Endif
;----------------------------------------------------------------------------
;判断是否有addr操作符
IfIDNi @SubStr( <arg>, 1, 5 ), <addr >
lea eax, @SubStr( <arg>, 6 )
_mov_ %count-1, eax ;这里是压入指针
Flags = 0
Endif
Endif
;----------------------------------------------------------------------------
If Flags
; % %out arg
mov eax, arg
_mov_ %count-1, eax ;直接压入寄存器
Flags = 1
Endif
Endm
Endif
call _Proc
endm
;函数结束定义
$Endp MACRO fname:REQ
% %out @CatStr( <fname>, < Endp > )
%out ==============================================================
% @CatStr( <fname>, < Endp > )
ENDM
;解析函数头, 然后生成定义
$ProcHead macro argHead:req
local Line, NewLine, FunName, ProcName
;Line textequ <argHead>
NewLine textequ @SubStr( %argHead, 1, @InStr( 1, %argHead, < > )-1 )
Line textequ @SubStr( %argHead, @InStr( 1, %argHead, < > ), @SizeStr(%argHead)-@InStr( 1, %argHead, < > )+1 )
FunName textequ @CatStr( %NewLine, < Proc SysCall >, %Line, < > )
%out ==============================================================
% %out FunName
% FunName
endm
;解析函数参数定义, 然后生成定义
$ProcArgc macro Line:req, Index:req
local NewLine, Define, Reg
If @InStr( 1, %Line, <:> ) ;如果中间有:号
NewLine textequ @SubStr( %Line, 1, @InStr( 1, %Line, <:> )-1 )
Else
NewLine textequ Line
Endif
Reg textequ < mm&Index >
Define textequ @CatStr( %NewLine, < textequ >, <!<>, %Reg, <!>> )
% %out Define
% Define
endm
;============================================================================
;声明一个符合Jcall的函数. 类似这种形式了
;$Proc Function1, uses ebx edi esi
;Function1是函数的名称. 后面是uses的寄存器列表. 基本上都是一样使用
;主要是和MASM 的函数顺序反着来的. 有点麻烦. 其他都一样. 现在有一个
;问题没有得到解决就是参数问题.. 无法命名参数, 现在参数第一个只能是
;mm0, 依次类推. 要搞个方法. 可以和MASM原生态支持的函数一样才舒服
;============================================================================
$Proc macro argList:vararg
local arg, position, Index
Index = 1
position = 0
% for arg, <argList>
Line textequ <arg>
If Index
$ProcHead Line ;解析函数头
Index = 0
Else ;这里就是解析参数的工作了
$ProcArgc Line, %position
position = position + 1
Endif
Endm
endm
Endif
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)