0

我有一个小程序,我试图用它来以编程方式识别 CPU 频率。

我的程序结构如下:

  • 设置闹钟
  • while(1)循环递增寄存器
  • 计算速度SIGALRM

最初,我正在使用

register unsigned int cycles asm("r6");  
...  
while(1)
    cycles++;

使用 objdump 后,我注意到这实际上转换为以下内容:

9aa0:       e1a03006        mov     r3, r6  
9aa4:       e2833001        add     r3, r3, #1  
9aa8:       e1a06003        mov     r6, r3  
9aac:       eafffffb        b       9aa0 <estimate_from_cycles+0x1cc>  

由于我不确定为什么将其翻译为 3 条指令,因此我尝试使用内联汇编来代替:

register unsigned int cycles asm("r6");  
...  
while(1)
    asm("add r6, r6, #1);

这翻译成:

9aa0:       e2866001        add     r6, r6, #1  
9aa4:       eafffffd        b       9aa0 <estimate_from_cycles+0x1cc>  
  • 为什么之前的实现翻译成 3 条指令?
  • 在 ARM 平台上,b <label>指令需要 3 个周期。但是,ARM 上的减法运算仅使用 1 个周期。
    • 有什么办法可以从 PC 寄存器中减去吗?
    • PC上是否允许减法?
    • 有没有其他方法可以减少实现相同逻辑所需的周期数?

编辑:我正在使用 CodeSourcery 的 arm-none-linux-gnueabi- 工具链,没有优化

4

1 回答 1

1

由于您没有启用任何优化,因此很可能将实现转换为 3 条指令。

但是,从快速测试来看,您似乎无论如何都必须编写内联汇编,因为当我使用以下命令编译以下内容时-O3 -fomit-frame-pointer

void test(void) {
        register unsigned int cycles asm("r6");
        while(1) cycles++;
}

例程简单地优化到

00000000 <test>:
   0:   eafffffe    b   0 <test>

即使添加volatile也是无用的,因为编译器肯定知道写入 CPU 寄存器肯定不会有任何副作用(与内存不同),因此对其进行优化是公平的。

回答你的其他问题,

  • 有什么办法可以从 PC 寄存器中减去吗?
  • PC上是否允许减法?

是的,当然了。但我不确定这是否仍然需要一个周期。

  • 有没有其他方法可以减少实现相同逻辑所需的周期数?

作为旁注,您的逻辑不会给出非常准确的结果,因为您的过程可能会在您开始和完成测量之间切换。

你期待:

<                    your process                     >
|<---------------your alarm duration----------------->|

什么时候,它可能更像(|上下文切换在哪里):

<your process> | <other processes ...> | <your process>
|<---------------your alarm duration----------------->|
于 2013-11-01T03:38:51.040 回答