gpt4 book ai didi

assembly - 如何正确使用 ADDIS 和 ADDI 将 32 位常量直接求和到寄存器?

转载 作者:行者123 更新时间:2023-12-02 03:16:36 27 4
gpt4 key购买 nike

我一直在尝试使用 ADDIS 和 ADDI 指令来实现将常量求和到数组的基本函数,我按照 https://cr.yp.to/2005-590/powerpc-cwg.pdf 第 48 和 49 页中的说明进行操作。 ,但行为不是我所期望的。

我想做的是在汇编程序中创建这个函数,但是对于某些常量ADDIS将它们减1,并且行为与手册所说的不一致,即检查是否设置了位16。GCC 和 clang 正确生成指令,他们使用的实际规则是什么?不按照手册所述增加或实现规则只会给我错误的总和。

在 ppc970 机器上测试,运行 64 位 Linux 内核和用户空间。

C 函数的编译器汇编器输出示例:

void func(int* r){
r[0] += r[0] + 0x9f321062; //addis r3,r3,0x9f32 #has bit 16 set to 1 but is not incremented.
//addi r3,r3,0x1062

r[1] += r[1] + 0x760ae53; //addis r4,r4,0x761 #compiler correctly increments this from 0x0760 to 0x0761, but bit 16 of this number is 0!
//addi r4,r4,0xae53
}

最佳答案

has bit 16 set to 1 but is not incremented.

PowerPC 的 addi 指令的工作方式与 MIPS CPU 上的同名指令类似:

您可以将 (-0x8000) 到 (+0x7FFF) 范围内的数字添加到寄存器。

addis 指令会将 0x10000 的倍数添加到寄存器中。

因为 0x9f321062 = 0x9f320000 + 0x1062,所以您可以通过使用一条 addis 和一条 addi 指令将 0x9f320000 和 0x1062 添加到寄存器,从而将 0x9f321062 添加到寄存器。

这里重要的是,16位数字0x1062的最高位是明确的,这意味着0x1062不大于0x7FFF,因此在addi可以处理的范围内。

现在让我们看看另一种情况:

0x760ae53 = 0x7600000 + 0xae53,因此您可以通过将 0x7600000 和 0xae53 添加到寄存器来将 0x760ae53 添加到寄存器。不幸的是,addi 只能在 (-0x8000) 到 (+0x7FFF) 范围内运行,因此添加 0xae53 不起作用。

如果addi操作数的最高位被设置,则addi指令对值进行符号扩展,这实际上意味着该指令相加(负值) (N-0x10000) 而不是(正值)N 到寄存器。

所以你必须按以下方式进行计算:

0x760ae53 = 0x7600000 + (0xae53 - 0x10000) + 0x10000 = 0x7610000 + (0xae53 - 0x10000)

换句话说:您必须将 addi 的操作数 (0x760) 加一,以补偿 addi 减去 0x10000 的影响。

bit 16

请注意,PowerPC 文档使用了非常困惑的位编号,甚至看起来每个 CPU 都不同:

32 位(!)汽车 PowerPC 的一些文档使用“位 32”(最高位)到“位 63”(最低位)的寄存器名称,因此位号 0 到 31 甚至不存在...

关于assembly - 如何正确使用 ADDIS 和 ADDI 将 32 位常量直接求和到寄存器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55946083/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com