如何在内联汇编中替换32位变量的字节?

时间:2013-08-20 05:41:39

标签: c gcc assembly inline-assembly avr

我希望用内联汇编替换32位值的最高字节,然后使用spi interace将缓冲区写入FRAM内存:

#define _load_op_code(op_code, addr)\
  __asm__ __volatile__ (\
  " ldi %D0, %1"     "\n\t"\
  : "=d"  ((uint32_t)addr)\
  : "M" (op_code)\
  )

#define SMEM_WREN   0x06
#define SMEM_WRITE  0x02

void fram_write(uint32_t addr, uint8_t *buf, uint16_t len) {
  FRAM_SELECT();
  spi_send_char(SMEM_WREN);
  FRAM_DESELECT();
  _load_op_code(SMEM_WRITE, addr);
  FRAM_SELECT();
  spi_send_32b(addr);
  spi_send(buf, len);
  FRAM_DESELECT();
}

在_load_op_code()内联汇编后,addr变量变得混乱 - 编译器使用为addr分配的寄存器作为其他操作的临时寄存器,并且我丢失了原始的addr值。 addr实际上是24位变量。这个代码有什么问题吗?

1 个答案:

答案 0 :(得分:1)

addr的原始值丢失,因为它被带有SMEM_WRITE和3个未定义字节的asm语句覆盖。从GCC手册:

  

普通输出操作数必须是只写的; GCC假定指令前这些操作数中的值已经死亡,无需生成。扩展的asm支持输入输出或读写操作数。使用约束字符“+”表示此类操作数,并将其与输出操作数一起列出。