指令段间及文件间参数调用过程(64位 Intel架构)

文章详细阐述了在64位Intel架构中,指令段间如何通过寄存器和栈进行参数调用,并通过C语言代码示例进行了验证。同时,介绍了文件间参数调用时使用extern关键字的方法。文章还包含了对call指令的解释。

指令段间及文件间参数调用过程(64位 Intel架构)

一. 指令段间的参数调用过程

1.1 推论

在汇编中,当一个指令段B调用指令段A的数据,是如何实现的呢?

首先指令段是由多个汇编指令集合而成(指令由操作码和操作数构成)。

而当指令段间调用参数,先需要一个指令段调用另一个指令段,换句话说,需要该指令段中的一个汇编指令调用另一个指令段名称,这里通过call指令调用(相关作用可看最后指令补充)如下图所示

在这里插入图片描述

而当指令段B调用指令段A相关数据时,可通过下面2种方式即可完成:

  1. 通过寄存器来相互调用

在这里插入图片描述

  1. 通过栈本身特性来进行调用:通过ebp指针移动,获取相关数据(32位机汇编可看到,读者可自行下载32位库,来进行实验)

在这里插入图片描述

以上为推论,下面通过C语言来进行验证

1.2 验证

编写一段2个指令段之间数据调用的C代码

#include <stdio.h>

int sum(int a, int b, int c){
        return a + b + c;
};
int main(){
        sum(1,2,3);
        return 1;
}

在Linux上,将代码编译成汇编代码

// -S 只编译
// -fno-asynchronous-unwind-tables 忽略调试代码
[root@localhost c-demo]# gcc -S -fno-asynchronous-unwind-tables lab.c

汇编代码

从下方代码可看出,main数中,将3个数据存放在寄存器中,sum通过寄存器取值并赋予在新开辟的栈空间中

ps:利用栈空间本身传递数值,可自行下载32位库进行操作

	.file	"lab.c"				// 文件名
	.text						// 代码段
	.globl	sum					// 全局 sum
	.type	sum, @function		// sum的类型为函数
sum:
	pushq	%rbp				// 开辟栈空间,并让bp(栈基址)指向该地址
	movq	%rsp, %rbp			// 让sp(栈针)指向bp所指向的地址
	movl	%edi, -4(%rbp)		// 开辟4字节大小的空间,并把edi里的值传送到该空间内
	movl	%esi, -8(%rbp)
	movl	%edx, -12(%rbp)
	movl	-4(%rbp), %edx		// 将第一个开辟的4字节空间的值存放到edx中
	movl	-8(%rbp), %eax      // 将第二个开辟的4字节空间的值存放到eax中
	addl	%eax, %edx			// 累加到edx中
	movl	-12(%rbp), %eax		// 将第三个开辟的4字节空间的值赋值到eax中
	addl	%edx, %eax			// 将edx值累加到eax中
	popq	%rbp				// 还原bp
	ret							// 返回
main:	
	pushq	%rbp				
	movq	%rsp, %rbp			
	movl	$3, %edx			// 将3存放到edx
	movl	$2, %esi
	movl	$1, %edi
	call	sum					// 调用sum指令段
	movl	$1, %eax			// 将产生的立即数丢给eax中
	popq	%rbp	
	ret

二. 文件间的参数调用过程

2.1 推论

若文件间调用,则需要其中一个文件调用另一个文件参数,这里就需要用到c语言中的关键字extern来指定所需调用的参数。

2.2 验证

编写2个C文件

demo.c

#include <stdio.h>
extern int data;
int sum(){
        return data;
}
int main(){
        sum();
        return 1;
}      

ex.c

int data = 1;

编写后,将两个文件进行编译

[root@localhost c-demo]#gcc -S -fno-asynchronous-unwind-tables demo.c
[root@localhost c-demo]#gcc -S -fno-asynchronous-unwind-tables ex.c

执行demo.c文件

[root@localhost c-demo]#gcc demo.s
/opt/rh/devtoolset-9/root/usr/libexec/gcc/x86_64-redhat-linux/9/ld: /tmp/ccnjTTw2.o: in function `sum':
demo.c:(.text+0x6): undefined reference to `data'
collect2: error: ld returned 1 exit status

单独执行demo.s文件会报错,因为不知道data是从哪个文件提取。

这时我们将2个汇编文件一起编译即可

[root@localhost c-demo]#gcc demo.s ex.s

三. 指令解释相关补充

call指令:保存当前过程链接地址,并调用指定指令段地址

摘自Intel手册 volume 2 Chapter3.2
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值