汇编函数中的参数传递

汇编函数中的参数传递

在 Xtensa 架构中,函数的参数传递通常遵循一定的约定。通常情况下,前几个参数通过寄存器传递,其余参数则通过堆栈传递。具体的参数传递规则可能会因编译器的不同而略有差异,但大多数情况下遵循以下规则:

参数传递规则
  • 前几个参数:

    • 最初的几个参数通常通过通用寄存器传递。
    • 对于 Xtensa 架构,前四个参数通常通过寄存器传递。
    • 具体而言,参数通常通过 a0a1a2 和 a3 寄存器传递。
  • 剩余参数:

    • 如果有超过四个参数,额外的参数通常通过堆栈传递。
    • 调用者负责在调用函数前将这些参数压入堆栈,并在返回后清理堆栈。
  • 返回值:

    • 单个的返回值通常通过寄存器 a0 传递。
    • 如果返回值较大(例如超过 32 位),则可能通过多个寄存器或堆栈传递。
示例

假设我们有一个函数 I2C_IRQHandler,它接受一个 u8 类型的参数 id。下面是使用 Xtensa 汇编实现该函数的一个示例,其中 a1 寄存器用于传递 id 的值。

asm

深色版本

1.globl I2C_IRQHandler
2I2C_IRQHandler:
3    // 加载 gIICDev 地址
4    movi.n a2, gIICDev  ; 假设 gIICDev 的地址存储在一个全局变量中
5
6    // 计算 dev 的地址
7    const16 a3, 0       ; 用于偏移量计算
8    const16 a3, sizeof(I2C_DEV)
9    muli a3, a3, a1     ; a3 = id * sizeof(I2C_DEV)
10    addi a2, a2, a3     ; a2 = gIICDev + id * sizeof(I2C_DEV)
11
12    // 加载 dev->instance->idr
13    l32i.n a3, a2, offsetof(I2C_DEV, instance.idr)
14    movi.n a4, IRQ_MASK  ; 假设 IRQ_MASK 是一个已知的常量
15    s32i.n a4, a3, 0
16
17    // 检查 dev->mode
18    l32i.n a3, a2, offsetof(I2C_DEV, mode)
19    cmpi.n a3, I2C_SLAVE
20    beqz a3, .end
21
22    // 调用 I2C_Slave_IRQHandle
23    movi.n a4, a2      ; 传递 dev 地址
24    call I2C_Slave_IRQHandle, a4
25
26    // 加载 dev->instance->ier
27    l32i.n a3, a2, offsetof(I2C_DEV, instance.ier)
28    s32i.n a4, a3, 0
29
30.end:
31    ret

参数传递详解

假设函数原型

c

深色版本

1void I2C_IRQHandler(u8 id);
汇编实现

asm

深色版本

1.globl I2C_IRQHandler
2I2C_IRQHandler:
3    // a1 寄存器中已经包含了 id 的值
4    // 加载 gIICDev 地址
5    movi.n a2, gIICDev  ; 假设 gIICDev 的地址存储在一个全局变量中
6
7    // 计算 dev 的地址
8    const16 a3, 0       ; 用于偏移量计算
9    const16 a3, sizeof(I2C_DEV)
10    muli a3, a3, a1     ; a3 = id * sizeof(I2C_DEV)
11    addi a2, a2, a3     ; a2 = gIICDev + id * sizeof(I2C_DEV)
12
13    // 加载 dev->instance->idr
14    l32i.n a3, a2, offsetof(I2C_DEV, instance.idr)
15    movi.n a4, IRQ_MASK  ; 假设 IRQ_MASK 是一个已知的常量
16    s32i.n a4, a3, 0
17
18    // 检查 dev->mode
19    l32i.n a3, a2, offsetof(I2C_DEV, mode)
20    cmpi.n a3, I2C_SLAVE
21    beqz a3, .end
22
23    // 调用 I2C_Slave_IRQHandle
24    movi.n a4, a2      ; 传递 dev 地址
25    call I2C_Slave_IRQHandle, a4
26
27    // 加载 dev->instance->ier
28    l32i.n a3, a2, offsetof(I2C_DEV, instance.ier)
29    s32i.n a4, a3, 0
30
31.end:
32    ret
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小蘑菇二号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值