avr-gcc 问题:忽略永久 variable/register 绑定。为什么?

avr-gcc woes: ignores permanent variable/register binding. Why?

仍在为 AVR 组装而苦苦挣扎。这次avr-gcc似乎完全无视我对permanently bind a local variable to a register的指令。这是一个例子——这当然只是一个例子,不是最终代码:

// C code:
ISR(USART1_RX_vect)
{
    register uint8_t c asm("r3") = UDR1;
    tty1::buffer[tty1::ptr.head] = c;
}

// Generated assembly:
000000d8 <__vector_20>:
  d8:   1f 92           push    r1
  da:   0f 92           push    r0
  dc:   0f b6           in      r0, SREG        ; 63
  de:   0f 92           push    r0
  e0:   11 24           eor     r1, r1
  e2:   8f 93           push    r24
  e4:   ef 93           push    r30
  e6:   ff 93           push    r31
  e8:   80 91 73 00     lds     r24, UDR1       ; 0x800073 <__EEPROM_REGION_LENGTH__+0x7f0073>
  ec:   e0 91 01 01     lds     r30, 0x0101     ; 0x800101 <tty<drv::uart1>::ptr>
  f0:   e2 95           swap    r30
  f2:   ef 70           andi    r30, 0x0F       ; 15
  f4:   f0 e0           ldi     r31, 0x00       ; 0
  f6:   ee 5f           subi    r30, 0xFE       ; 254
  f8:   fe 4f           sbci    r31, 0xFE       ; 254
  fa:   80 83           st      Z, r24
  fc:   ff 91           pop     r31
  fe:   ef 91           pop     r30
 100:   8f 91           pop     r24
 102:   0f 90           pop     r0
 104:   0f be           out     SREG, r0        ; 63
 106:   0f 90           pop     r0
 108:   1f 90           pop     r1
 10a:   18 95           reti

- 请给我r3

- 当然可以!这是 r24

我可以询问 r2r7 之间的任何寄存器,编译器只需要它想要的任何东西!它与 UDR1 无关,它与我分配的任何内容 c 一样。如果它什么都不做,那条指令有什么意义呢?我应该如何控制编译器选择的寄存器?

对于问题 «为什么我要将变量分配给寄存器?» 我回答 «因为生成的代码对于一个中断,我想对生成的程序集进行精细控制。» 到目前为止,这对我来说是个麻烦。

仍在使用 avr-gcc 版本 7.1.0...

从中断服务例程 (ISR) 中删除对全局范围的声明。 GCC 允许全局和本地永久绑定。你的在 ISR 范围内,但对你来说没用。

我会尽力给出更详细的解释。

本地范围

  1. 从绑定中注册不再是寄存器,而是作为存储位置。
  2. 相同的优化规则适用于任何其他自动变量。
  3. ISR 必须恢复所有寄存器(绑定在全局范围内的寄存器除外)- 因此不会产生副作用 - 即使寄存器绑定在本地范围内也是如此。

见代码: https://godbolt.org/g/HsjvCa and https://godbolt.org/g/ZGjvRE 开启优化。

本地绑定不会更改任何通用寄存器使用规则。

如果您绑定寄存器 - 您将无法调用任何没有使用寄存器绑定(全局范围)的头文件编译的函数。在本地范围内调用任何函数都会使本地绑定无效。