您现在的位置: 首页 > 网站导航收录 > 百科知识百科知识
如果一个函数需要传递大量的参数,显然寄存器是不够用的,应该如何解决?
堆栈,参数,函数如果一个函数需要传递大量的参数,显然寄存器是不够用的,应该如何解决?
发布时间:2019-02-08加入收藏来源:互联网点击:
如果一个函数需要传递大量的参数,显然寄存器是不够用的,应该如何解决?
回答于 2019-09-11 08:43:50
回答于 2019-09-11 08:43:50
我们无论学习什么语言,都离不开函数、参数、参数传递、函数调用、返回值等这几个步骤。
我们在编写一个汇编函数时,用寄存器传参的方式,要提前约定好参与函数功能的寄存器,将参数存入函数约定好的寄存器中,在进行运算。
那么问题来了,我们知道的寄存器也就那么几十个,如果一个函数需要传递大量的参数,显然寄存器是不够用的,就需要用到堆栈传参的方式去解决。
【堆栈传参的方式】
堆栈传参看到这几个字肯定能想到将参数保存在堆栈中。那我们该怎么用哪?同样用例题介绍堆栈传参的方式。
例:编写一个函数,实现任意五个整数相加。
分析:需要将5个参数保存到堆栈中,用CALL指令调用函数。
第一步:在DTDebug.exe软件中打开飞鸽软件,如图2-13-1所示。
第二步:将5个整数压入堆栈,输入以下指令,如图2-13-2所示。
PUSH 1
PUSH 2
PUSH 3
PUSH 4
PUSH 5
第三步:依次按F8将参数压入堆栈中,如图2-13-3所示。
按F8执行完看到,堆栈中已经压入我们传递的参数。用CALL调用函数,我们怎么编写这个函数哪?
我们的常用指令不允许两边都为内存,所以我们通过ESP栈顶指针来运算。
如果这么写:MOV EAX,DWORD PTR DS:[ESP],那么EAX里的值是什么?
我们编写完参数后,调用CALL,会将CALL下一行的指令地址传入堆栈,这个时候ESP的值就是CALL函数地址,堆栈的变化如图2-13-4:
图2-13-4 堆栈图
第三步:编写函数,输入以下指令,如图2-13-5所示。
这5个参数依次是:ESP+0x14、ESP+0x10、ESP+0xC、ESP+0x8、ESP+0x4
所以我们的函数可以这样编写:
MOV EAX,DWORD PTR DS:[ESP+0x14]
ADD EAX,DWORD PTR DS:[ESP+0x10]
ADD EAX,DWORD PTR DS:[ESP+0xC]
ADD EAX,DWORD PTR DS:[ESP+0x8]
ADD EAX,DWORD PTR DS:[ESP+0x4]
RETN
第四步:使用CALL调用函数,输入CALL 0x77068E4D,如图2-13-6所示。
第五步:按F7观察堆栈窗口数据变化,如图2-13-7所示。
图2-13-7中,执行完CALL指令,并将CALL指令下一行地址压入堆栈中,当前黑色定位光标在函数体开始的地址,当前ESP是0x0019FFD8,堆栈窗口中的内存使用是从高地址向低地址使用的,所以ESP+14是参数的开始。我们可以双击堆栈窗口中的内存地址,如图2-13-8所示。
第六步:把EAX寄存器的数据变为0x00000000,依次按F8,查看结果是否正确,如图2-13-9所示。
1+2+3+4+5=15,转化成16进制为F。看图2-13-9中,EAX寄存器的值为0x00000000F,说明运算结果正确,证明我们编写的函数是正确的。
第七步:按F8执行RETN指令,如图2-13-10所示。
以上是堆栈传参的过程,总结:堆栈传参是将参数压入堆栈中,函数在运算时通过ESP寻址的方式去查找对应的参数并进行运算。
思考:函数执行完了,可是我们的数据还保存在堆栈中,该怎么解决呢?
回答于 2019-09-11 08:43:50
如果太多参数,最好修改设计。实在不行c语言只能用全局变量来处理了。
回答于 2019-09-11 08:43:50
寄存器传参数主要是少量速度要求高的参数
实际比较多的参数是通过堆栈传递的,call指令前要把需要的参数压栈
如果是比较大的连续的数据结构,就不要整个数据结构压栈了,把指针压栈传递过去就行了
上一篇:苏炳添赛后气喘吁吁地接受记者采访,网友心疼他“不能等休息好了采访吗”,你怎么看?
下一篇:返回列表
相关链接 |
||
网友回复(共有 0 条回复) |