C++协程在Linux中的汇编实现

文章详细解释了X86-64架构下的寄存器使用,特别是在函数调用中如何通过寄存器和栈空间存储数据以支持协程。同时介绍了gcc内联汇编的应用以及协程栈的测试,展示了函数调用时对栈的操作过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

协程的汇编实现

1 寄存器

X86-64有16个64位寄存器,分别是:%rax,%rbx,%rcx,%rdx,%esi,%edi,%rbp,%rsp, %r8,%r9,%r10,%r11,%r12,%r13,%r14,%r15。其中:

  • %rax 作为函数返回值使用
  • %rsp %rbp 栈指针寄存器,指向当前函数栈的栈顶和栈底
  • %rdi,%rsi,%rdx,%rcx,%r8,%r9 用作函数参数,依次对应第1-6参数
  • %rbx,%rbp,%r12,%r13,%r14,%r15 用作数据存储,遵循被调用者使用规则,简单说就是随便
    用,调用子函数之前要备份它,以防他被修改
  • %r10,%r11 用作数据存储,遵循调用者使用规则,简单说就是使用之前要先保存原值
  • %rip:用于存放下一条指令地址,CPU会取此寄存器的地址去找到下一条指令并执行。
  • 关于寄存器可以参考csapp中的图片:
    在这里插入图片描述
2 函数调用

函数调用是从一个函数栈跳转到相邻的另一个函数栈。由于调用返回后还需恢复原函数栈的状态,因此必须在调用时通过寄存器和栈空间的配合来存储一些数据,方便调用完成后恢复。具有调用关系的两个函数栈空间一定是相邻的,也就是说主调方的函数栈空间与被调方的函数栈空间一点是相邻的。

add.c

int add(int a, int b){
   
    return a+b;
}

int main(){
   
    int a = 1;
    int b = 2;
    int x = add(a,b);
    return 0;
}

add.s

	.file	"add.c"
	.text
	.globl	add
	.type	add, @function
add:
.LFB0:
	.cfi_startproc
	pushq	%rbp 				;将main函数帧的起始位置压栈,记在add函数帧里
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp			;将add函数帧的栈顶位置赋给%rbp,没有像main修改%rsp
	.cfi_def_cfa_register 6
	movl	%edi, -4(%rbp)		;第一个参数放入add函数帧
	movl	%esi, -8(%rbp)		;第二个参数放入add函数帧
	movl	-4(%rbp), %edx
	movl	-8(%rbp), %eax
	addl	%edx, %eax			;结果交给%eax做为返回值
	popq	%rbp				;%rbp恢复为main函数帧的起始位置
	.cfi_def_cfa 7, 8
	ret							;把main函数的返回地址赋值给%rip,下一步CPU会调到该地址的指令执行
	.cfi_endproc
.LFE0:
	.size	add, .-add
	.globl	main
	.type	main, @function
main:
.LFB1:
	.cfi_startproc
	pushq	%rbp				
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$16, %rsp			;%rsp下移16,为main函数栈预留空间
	movl	$1, -12(%rbp)
	movl	$2, -8(%rbp)
	movl	-8(%rbp), %edx
	movl	-12(%rbp), %eax
	movl	%edx, %esi
	movl	%eax, %edi
	call	add					;调用add函数,此步骤会将main函数的返回地址压入栈,然后将add函数入口地址赋值给%rip,下一步CPU就会执行到add函数
	movl	%eax, -4(%rbp)
	movl	$0, %eax
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE1:
	.size	main, .-main
	.ident
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值