"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_val
和 data_val
,因此 ptr_val
和 ptr_addr
未定义。
这是我用来在内存中写入一些数据以进行调试的代码(直到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_val
和 data_val
,因此 ptr_val
和 ptr_addr
未定义。