029-【X86-汇编语言】-过程--参数传递

参数

C语言的函数可以传递参数,如下add函数接受两个参数X和Y,并计算它们的和。

int add(int x, inty)

汇编语言的过程也可以传递参数。确切地说汇编的过程是没有“参数”这个概念的,这里使用“参数”这个词只是为了便于大家理解。参数的本质是调用者传递给被调用者的数据。

传参方式

传递参数的方式称为传参方式。我能想到的汇编语言传参方式有以下三种。

寄存器传参方式

寄存器传参方式是将传递的数据保存到寄存器中供子过程使用

.386
.model stdcall, flat
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD

.code
SUBP PROC
	ADD EAX,EBX
	RET
SUBP ENDP

MAIN PROC
    MOV EAX, 1 ;将第一个数字保存到EAX
    MOV EBX, 2 ;将第二个数字保存到EBX
    CALL SUBP
	INVOKE ExitProcess, 0
MAIN ENDP
END MAIN

寄存器传参方式的缺陷是,寄存器数量有限。并且要求调用方和被调用方必须小心翼翼地设置、保存、回复各寄存器的值。

数据段传参方式

数据段传参方式是将要传递的数据保存在数据段内供子过程使用

.386
.model stdcall, flat
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD

.data
ADD1 DWORD ?
ADD2 DWORD ?

.code
SUBP PROC
	MOV EAX, ADD1
    ADD ADD2,EAX
	RET
SUBP ENDP

MAIN PROC
    MOV ADD1, 1 ;将第一个数字保存到ADD1
    MOV ADD2, 2 ;将第二个数字保存到ADD2
    CALL SUBP
	INVOKE ExitProcess, 0
MAIN ENDP
END MAIN

使用数据段变量传参的缺陷是,必须声明好所有的参数。更要命的是如果是递归调用,必须明确递归的次数,以便声明每次递归所要使用的变量,因为每次递归不能覆盖上一次参数变量的值。而动态声明变量几乎是不可能的(其实是用办法的,这里你得自己思考动态声明变量是多么复杂)。

堆栈段传参方式

堆栈方式是将要使用的参数push到堆栈,然后子程序通过读取堆栈的值获取数据。子程序先将ESP的值赋值到EBP中,使EBP等于ESP,然后通过EBP+偏移量的方式获取到参数的值。

.386
.model stdcall, flat
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD

;堆栈传参
.code
SUBP PROC
	MOV EBP, ESP
	MOV EAX,[EBP+8]; EBP+8是第一个数字在栈内的地址
	ADD EAX,[EBP+4]; EBP+4是第二个数字在栈内的地址
	RET
SUBP ENDP

MAIN PROC
	MOV EAX,1
    PUSH EAX ;将第一个数字入栈
	MOV EAX,2
    PUSH EAX ;将第二个数字入栈
    CALL SUBP
	INVOKE ExitProcess, 0
MAIN ENDP
END MAIN

相较与其他两种传参方式,通过堆栈传参明显更加便捷。不过现在还面临一个问题,如果没人将参数出栈会浪费栈空间,另外在嵌套调用的时候也会存在一些问题。一下接将继续讨论

猜你喜欢

转载自blog.csdn.net/patronwa/article/details/90754532