"undefined named operand" arm64 内联汇编错误

"undefined named operand" error in arm64 inline assembly

这是我用来在内存中写入一些数据以进行调试的代码(直到u-boot程序中可以使用printf)。变量 myptr 位于 .__mydebug 部分,每写入 8 个字节后它增加 8,我想以 {debug_tag, debug_value} 对的形式写入我感兴趣的任何值。这里 debug_tag 是显示调试数据序列的一些值,而 debug_value 是我想在调试期间检查(或查看)的值。这是arm64汇编。

.global myptr

ldr x28, =myptr   /* load the address of myptr */
add x28, x28, #8  /* set write pointer to the next address after the myptr variable */
mov x27, #0x33   /* first debug write starts with tag value 0x33 */
str x27, [x28], #8   /* write the tag value, increment the pointer */
mov x27, some_value   /* some_value : the value I want to see with tag value 0x33 */
str x27, [x28], #8   /* write the debug value, increment the pointer */    ldr x26, =myptr    /* load pointer address */


/* next debug write, in the same assembly code, x28 hasn't changed, so use as is */
mov x27, #0x34  /* new debug tag */
str x27, [x28], #8  /* write new tag, increment pointer */
mov x27, some_another_value  /* another data I want to check */
str x27, [x28], #8  /* write the data, increment pointer */
ldr x26, =myptr  /* load the address of myptr to x26 */
str x28, [x26]   /* save the updated pointer in myptr, just in case x28 is modified and \
                   the pointer should be used later in assembly or C code .. */
.... (skip) ....

.section .__mydebug
myptr: .double 0x0
data_start: .double 0x0

所以这是在有效的内存部分中顺序写入调试信息。
我可以稍后在 .c 程序中继续此调试写入,如下所示,它也有效。

// debug print 
int xx=sizeof(struct global_data);
*((uint64_t *)myptr) = 0x101; myptr+=8;  /* debug tag start with 0x101 here */
*((uint64_t *)myptr) = xx; myptr+=8;     /* write some data I want to check.. */
*((uint64_t *)myptr) = 0x102; myptr+=8;  /* another debug tag */
*((uint64_t *)myptr) = base; myptr+=8;    /* another value I want to check */

好的,我可以接受。但这看起来不太好,也很不方便。
所以我很好奇如何使用带有内联汇编的函数在 C 程序中执行上述操作。我想将标记值和调试值(64 位)作为参数传递给函数。该函数应检索 myptr 值以写入标签和数据,并且应每次更新 myptr 值。我试着在下面写了一个函数。

void dbg_print(unsigned int tag, uint64_t data)
{
    uint64_t ptr_addr1;
__asm (
    "ldr %[ptr_addr], =myptr" \
    "ldr %[ptr_val], [%[ptr_addr]]" \
    "str %[tag_val], [%[ptr_val]], #8" \
    "str %[data_val], [%[ptr_val]], #8"
    : /* no output */ \
    : [tag_val] "r" (tag), [data_val] "r" (data) /* input list */ \
    : "memory" /* no specific clobbered register, but memory modified */
);
}

当我编译它时,我得到这个编译错误。

common/init/board_init.c: In function 'dbg_print':
common/init/board_init.c:144:1: error: undefined named operand 'ptr_addr'
  144 | );
      | ^
common/init/board_init.c:144:1: error: undefined named operand 'ptr_val'
common/init/board_init.c:144:1: error: undefined named operand 'ptr_addr'
common/init/board_init.c:144:1: error: undefined named operand 'ptr_val'
common/init/board_init.c:144:1: error: undefined named operand 'ptr_val'
make[2]: *** [scripts/Makefile.build:254: spl/common/init/board_init.o] Error 1
make[1]: *** [scripts/Makefile.spl:515: spl/common/init] Error 2

我无法理解 undefined named operand 错误。我需要在模板中的某处定义操作数吗?在https://www.keil.com/support/man/docs/armclang_ref/armclang_ref_qbn1517569205870.htm中的例子中,模板中的操作数只是使用,没有定义。 C中的变量无论如何都被声明了,但是汇编模板中的操作数不是被编译器替换了吗?
感谢您阅读,如果有人能向我澄清这件事,我将不胜感激。

添加:
阅读 Nate Eldredge 和 Peter Cordes 的评论后,我意识到 'defining the operand' 意味着使用操作数说明符(那些在 : 之后并与 : 连接的字段)将值连接到 C 世界。所以我尝试将代码更改为此,然后看看是否可行。

void dbg_print(unsigned int tag, uint64_t data)
{
    uint64_t ptra, ptrv;
__asm (
    "ldr %[ptr_addr], =myptr \n"   /* get pointer address */
    "ldr %[ptr_val], [%[ptr_addr]] \n"    /* get pointer value */
    "str %[tag_val], [%[ptr_val]], #8 \n"   /* write to pointed addr */
    "str %[data_val], [%[ptr_val]], #8 \n"   /* write to pointed addr */
    : [ptr_addr] "=r" (ptra), [ptr_val] "=r" (ptrv)
    : [tag_val] "r" (tag), [data_val] "r" (data) /* input list */
    : "memory" /* no specific clobbered register, but memory modified */
    );
}

I can't understand undefined named operand error. Do I need to define the operand in the template somewhere? In the example in https://www.keil.com/support/man/docs/armclang_ref/armclang_ref_qbn1517569205870.htm, the operands in the template are just used without defining.

是的,您需要在 asm 语句的输入或输出中定义它们。您 link 的示例都定义了它们使用的所有名称。您的代码只是在那里定义了 tag_valdata_val,因此 ptr_valptr_addr 未定义。