Win32ASM学习笔记(五)

Win32ASM学习笔记(五)
相关链接:
Win32 ASM学习笔记(一)
Win32 ASM学习笔记(二)
Win32 ASM学习笔记(三)
Win32 ASM学习笔记(四)

程序中子程序调用:

1>     子程序名 proc [距离][语言类型][可视区域][USES寄存器列表][,参数:类型]…[VARARG]         local 局部变量列表

…..指令

子程序名 endp

2>     proc 和endp 伪指令定义了子程序开始和结束的位置,proc后面跟的参数是子程序的属性和输入参数。子程序的属性:

a)距离   可以是NEAR,FAR,NEAR16,NEAR32,FAR16或FAR32,Win32中只有一个平坦的段,无所谓距离,所以对距离的定义往往忽略。

b)语言类型   表示参数的使用方式和堆栈的方式,可以是stdcall,c,syscall,basic,fortran和pascal,如果忽略,则使用程序头部.model定义的值。

c)可视区域   可以是private,public 和export。Private表示子程序只对于本模块可见:public表示对所有的模块可见(在最后编译连接完成的.exe文件中);export表示是导出的函数,当编写DLL的时候要将某个函数导出的时候可以这样使用。默认的设置是public

d)USES寄存器列表  表示由编译器在子程序指令开妈前自动安排push这些寄存器的指令,并且在ret前自动安排pop指令,用于保存执行环境,但笔者认为不如自己在开头和结尾用pushad和popad指令一保存和恢复所有寄存器来得方便.

e)参数和类型   参数指参数的名称,在定义参数名的时候不能跟全局变量和子程序中的局部变量重名。对于类型,由于Win32中的参数类型只有32位(dword)一种类型,所以可以省略。在参数定义的最后还可以跟vararg的API就是wsprintf,类型于C语言中的printf,其参数的个数取决于要显示的字符串中指定的变量个数。

完成了定义之后,可以用invoke伪指令来调用子程序,当invoke伪指令位于子程序代码之前的时候,处理到invoke语句的时候编译器还没有扫描到子程序定义信息的记录,所以会有以下错误的信息:error A2006:undefined symbol:ProcWinMain

这并不是说子程序的编写有错误,而是invoke伪指令无法得知子程序的定义情况,所以无法进行参数的检测。在这种情况下,为了让invoke指令能正常使用,必须在程序的头部用proto伪操作定义子程序的信息,“提前”告诉invoke语句关于子程序的信息。(由于程序的调试过程中可能常常对一些子程序的参数个数进行调整,为了使它们保持一致,就需要同时修改proc语句和proto语句,在写源程序的时候有意识地把子程序的位置提到invoke语句的前面,省略掉proto语句,可以简化和避免出错。)

f)MASM用local伪指令提供对局部变量的定义。定义格式:

  local  var1 [[重复数量]][:type],var2[[]重复数量][:type]…local为伪指令必须紧接在子程序的伪指令proc后,其他指令开始前,这是因为局部变量的数目必须在子程序开始的时候,可以有多个local语句,语法中的数据类型不能用缩写,如果要定义数据结构,可以用数据结构的名称当做类型。Win32汇编默认的类型是dword,如果定义dword类型的局部变量,则类型可以省略。当定义数组的时候,可以[]括号括起来。不能使用定义全局变量的dup伪指令。

注:WinMain proc   ;函数名

       local @stWndClass:WNDCLASSEX ;WNDCLASSEX结构体类型成员

       local @stMsg:MSG;MSG结构体类型成员

3>     使用invoke语句

a)       API是可以被Win32ASM调用的。但是有一个问题就是,Win32API动辄就是十几个参数,整个源程序一眼看上去基本上都是把参数压入堆栈的push指令,参数的个数和顺序很容易搞错,由此引起的莫名其妙的错误源源不断,源程序的可读性看上去也很差。如果写的时候少写了一名push指令,程序在编译和链接的时候都不会报错,从但是程序在执行的时候必定会崩溃,原因是堆栈对不齐了。但是在这方面Microsoft帮了我们一把,在MASM中提供了一个伪指令实现了这个功能,就是invoke伪指令。

格式:invoke 函数名,[,参数1],[,参数2]…….

EG:invoke MessageBox,NULL,OFFSET szText,offset szCaption,MB_OK

说明:invoke并不是80386处理器的指令,而是一个MSAM编译器的伪指令,在编译的时候它把上面的指令展开我们需要的4个push指令和1个Call指令,同时,进行参数数量的检查工作,如果带的参数数量和声明时的数量不符,编译器会报一个:error A1237:too few arguments to invoke


来源: http://www.programbbs.com/bbs/view29-8725-1.htm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值