2.13 堆栈传参

2.13 堆栈传参

首页休闲益智堆栈平衡更新时间:2024-05-09
2.13 堆栈传参

为什么学习本节内容?因为我们要学习汇编语言中参数传递的方式,而堆栈传参会使我们工作效率提高。

本节必须掌握的知识点:

掌握参数传递的方式

熟练使用堆栈传参

我们无论学习什么语言,都离不开函数、参数、参数传递、函数调用、返回值等这几个步骤。在上节中我们介绍了函数及函数调用并简略的说了一下参数、参数传递、返回值。本节将继续探讨参数传递。

2.13.1【参数传递方式】

参数传递的方式有两种:

1、寄存器传参

2、堆栈传参

【寄存器传参的方式】

在上一节中我们做了一个例子,编写一个函数,实现任意两个整数相加,就是用的寄存器传参的方式介绍的,下面是完整代码。

MOV ECX ,1

MOV EDX ,2

CALL 0x77068E51 (注:CALL后面跟的地址要根据你自己编写的函数实际情况来定)

这里是函数体,实现任意2个整数相加的函数

0x77068E51 ADD ECX,EDX (ECX存储的数据 EDX存储的数据的值保存到ECX中)

MOV EAX,ECX (所得到的结果放到EAX中)

RETN

已经写出来了代码,可还是不知道什么是寄存器传参。我们分析上面代码来介绍寄存器传参。

根据题意知,任意两个整数,这里知道这两个整数是存在,根据代码可知我们假设的这两个整数分别为1、2,那存在哪里呢?根据

MOV ECX,1

MOV EDX,2

可知把1保存在了ECX中,把2保存在了EDX中,ECX、EDX大家都知道这是寄存器,把两个整数保存在了寄存器里,执行CALL指令后,重点来了。

根据

ADD ECX,EDX

MOV EAX,ECX

这两行指令我们知道了,实现两个整数相加的功能,是通过寄存器中保存的数据相互做运算的,运算的结果保存在了EAX中。这是我们自己约定用寄存器传参的方式。

总结:我们在编写一个汇编函数时,用寄存器传参的方式,要提前约定好参与函数功能的寄存器,将参数存入函数约定好的寄存器中,在进行运算。

那么问题来了,我们知道的寄存器也就那么几十个,如果一个函数需要传递大量的参数,显然寄存器是不够用的,那该怎么解决哪?需要用到堆栈传参的方式去解决。

【堆栈传参的方式

堆栈传参看到这几个字肯定能想到将参数保存在堆栈中。那我们该怎么用哪?同样用例题介绍堆栈传参的方式。

例:编写一个函数,实现任意五个整数相加。

分析:需要将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寻址的方式去查找对应的参数并进行运算。

那么问题来了,我们的函数执行完了,可是我们的数据还保存在堆栈中,该怎么解决呢?

下节我们解答这个问题。

下节介绍堆栈平衡。

练习:

1、用汇编编写一个函数,功能是实现对任意10个整数的加法运算(不考虑溢出),

要求:

1、前两个参数使用寄存器进程参数传递;

2、后8个参数使用堆栈进行传递。

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved