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

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

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

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

文章目录

  • 指令段间及文件间参数调用过程(64位 Intel架构)
    • 一. 指令段间的参数调用过程
      • 1.1 推论
      • 1.2 验证
    • 二. 文件间的参数调用过程
      • 2.1 推论
      • 2.2 验证
    • 三. 指令解释相关补充

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

1.1 推论

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

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

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

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

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

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

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

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

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

以上为推论,下面通过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				// 还原bpret							// 返回
main:	pushq	%rbp				movq	%rsp, %rbp			movl	$3, %edx			// 将3存放到edxmovl	$2, %esimovl	$1, %edicall	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
指令段间及文件间参数调用过程(64位 Intel架构)