指令段间及文件间参数调用过程(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