指令段间及文件间参数调用过程(64位 Intel架构)
文章目录
- 指令段间及文件间参数调用过程(64位 Intel架构)
- 一. 指令段间的参数调用过程
- 1.1 推论
- 1.2 验证
 
- 二. 文件间的参数调用过程
- 2.1 推论
- 2.2 验证
 
- 三. 指令解释相关补充
 
一. 指令段间的参数调用过程
1.1 推论
在汇编中,当一个指令段B调用指令段A的数据,是如何实现的呢?
首先指令段是由多个汇编指令集合而成(指令由操作码和操作数构成)。
而当指令段间调用参数,先需要一个指令段调用另一个指令段,换句话说,需要该指令段中的一个汇编指令调用另一个指令段名称,这里通过call指令调用(相关作用可看最后指令补充)如下图所示

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

- 通过栈本身特性来进行调用:通过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
 



















