How to relace byte of 32bit variable in inline assembly?-Collection of common programming errors

I want to replace the highest byte of 32bit value with inline assembly, following code writes buffer to FRAM memory with spi interace:

#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();
}

after _load_op_code() inline assembly addr variable gets cluttered – compiler use registers allocated for addr as temporary registers for other operations and i lose original addr value. addr is in fact 24bit variable. Any idea whats wrong with this code?

  1. The original value of addr is lost because it is overwritten by the asm statement with SMEM_WRITE and 3 undefined bytes. From the GCC manual:

    The ordinary output operands must be write-only; GCC assumes that the values in these operands before the instruction are dead and need not be generated. Extended asm supports input-output or read-write operands. Use the constraint character ‘+’ to indicate such an operand and list it with the output operands.

Originally posted 2013-11-09 22:42:43.