首页
社区
课程
招聘
创建一种新的调用方式, 利用MMX传递参数
发表于: 2011-10-14 15:12 4452

创建一种新的调用方式, 利用MMX传递参数

2011-10-14 15:12
4452
最近我看着那些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期)

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 878
活跃值: (496)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
很好。可惜有点麻烦。
2011-10-14 18:23
0
游客
登录 | 注册 方可回帖
返回
//