注册 登录
编程论坛 汇编论坛

win32 函数指针的问题

codeos 发布于 2011-03-27 14:25, 1362 次点击
看个情景先:
------------------------------------------------
;code start
 1|_Fun    proc    _Arg    ;自定义的一个子函数,调用时需要传入一个dword类型参数        
 2|    pushad
 3|    mov    eax,esi
 4|   ......              ;总之是一些简单的操作
 5|    popad
 6|    ret
 7|_Fun    endp
 8|
 9|_WinMain    proc        ;主函数
10|    local    @tmp
11|    local    @arg
12|    mov        @arg,1234h
13|    mov        @tmp,offset _Fun
14|    invoke    _Fun,@arg
15|    invoke   
16|_WinMain    endp
;code end
---------------------------------------------------------------
我在主函数_WinMain中invoke了自定义的子函数_Fun,没什么问题;
在代码的第13行我获取了子函数的偏移地址,这样如果我不想用子函数名_Fun去调子函数,
而是想通过那个存放子函数地址的@tmp局部变量去调子函数,该如何操作?
我试过这个样子去调子函数:
    invoke    @tmp,@arg
编译器会报错:error A2190: INVOKE requires prototype for procedure

我应该怎样通过那个子函数的地址去访问带参数的子函数?
11 回复
#2
zklhp2011-03-27 20:50
1 函数指针是C里面的概念 在汇编里可以说就是函数第一条指令的地址 甚至 汇编里根本没函数。。

2 这个 最简单的方法是用指令 也就是 类似 push XXX push XXX call 一类的操作 达到你说的的效果 当然麻烦

3 INVOKE requires prototype for procedure 嘛意思呢 简单的说 要求类型声明

invoke这个宏的用法就是你举的 更灵活的用法 这个宏是不支持的

罗云彬大大在写远线程的时候写过一个很灵活的invoke宏 摘录如下

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; 将参数列表的顺序翻转

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

reverseArgs   macro arglist:VARARG

        local txt,count

 

      txt   TEXTEQU <>

    count = 0

    for   i,

        count = count + 1

        txt   TEXTEQU @CatStr(i,,<%txt>)

      endm

    if    count GT 0

        txt   SUBSTR  txt,1,@SizeStr(%txt)-1

    endif

      exitm txt

endm

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; 建立一个类似于 invoke 的 Macro

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

_invoke   macro _Proc,args:VARARG

        local count

 

    count = 0

%   for   i,< reverseArgs( args ) >

          count = count + 1

      push     i

    endm

      call     dword ptr _Proc   

 

endm

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

可以实现 具体的请自行参考《Windows环境下32位汇编语言程序设计》

4 貌似写类型转换也可以 我试试再说罢。。

#3
zklhp2011-03-27 21:02
;#Mode=CON
;MASMPlus 单文件代码模板 - 控制台程序
;--------------------------------------------------------------------
;单个文件需要指定编译模式,否则默认是EXE方式,在系统设置中可以设置默认是DOS还是Windows.
;编译模式自带了DOS/COM/CON/EXE/DLL/LIB这几种,如果有必要,可以更改ide.ini添加新的编译模式
;当然,更好的是创建为一个工程.更方便及易于管理,使用方法:按Ctrl多选->创建工程.必须有多个文件

.386
.model flat, stdcall
option casemap :none

include windows.inc
include user32.inc
include kernel32.inc
include masm32.inc

includelib user32.lib
includelib kernel32.lib
includelib masm32.lib
include macro.asm

.data?
    buffer    db 100 dup(?)
    lpFunc    dd ?
.CODE

Func typedef proto :DWORD

_Func proc _Arg
    invoke StdOut,CTXT("Hello World!")
    ret
_Func endp

START:
   
    mov lpFunc,_Func
    invoke (Func ptr _Func),5
   
    ;暂停显示,回车键关闭
    invoke StdIn,addr buffer,sizeof buffer
    invoke ExitProcess,0
   
end START
#4
zklhp2011-03-27 21:03
对于win32asm来说写这种类型转换挺无聊的

上面的也实现了这个功能 但比较难理解

三种方法 自己选一种罢。。
#5
zklhp2011-03-27 21:05
哦 我给的那个需要MasmPlus支持 不过你看主要的代码就好了

Func typedef proto :DWORD

invoke (Func ptr _Func),5

牵扯到typedef prote ptr的用法 有兴趣自己学 不会再来问
#6
你们都要疼我哦2011-04-02 09:49
proto吧  最简单。push/call 也行  注意类型。
#7
2011-04-02 23:14
前边两位已经解释的很完美了。 我也跟着学到了不少

我补充一下哈  汇编里貌似没有类型的概念  只有长度  还有。楼主你的代码很不好哈

为什么定义局部变量不指定类型呢???函数形参也不指定  这很不好哈  关于你说的

其实很简单哈   因为函数名  和跳转标号都一样  他最好被翻译的都是一个地址

比如_Fun;  最好也是被翻译成一个地址常量
_ERROR_PROC:  标号  它也是被翻译成一个地址常量

所以你用mov ebx, offset _Fun   拿到函数地址   直接就可以用call ebx  就可以拉

汗 发现现在写代码  写完习惯性的加个";"  幸好在汇编里没问题
#8
zklhp2011-04-04 12:48
汇编里貌似没有类型的概念 我觉得这个概念关键看怎么说。。
#9
zklhp2011-04-04 12:49
还有 初学能思考到这个问题很不错。。
#10
你们都要疼我哦2011-04-04 16:56
其实楼主的代码是挺不错。只不过我们看不习惯而已。
win32宏汇编还是有类型的。即使是纯粹的汇编,逻辑上还是
有类型的。
#11
2011-04-05 00:12
额  有类型???我怎么感觉就只有宽度 比如db dw dd dq  

其他的象C语言里的  4个字节长的我都用DWORD   当然要是win32用API编写

我肯定也会用一些typedef重定义的  LPVOID  HANDLE这些东东  主要为了代码好看
#12
superzwd2011-04-15 10:27
LZ想法是好的,就是编译器不支持,如果LZ能自己弄个编译器就没这个烦恼了

编译器也是人编的,所以我们用人家的编译器就要遵守人家的规则,这个没办法的.
1