我正在try 使用内联拇指程序集将地址从c指针读入寄存器.

这是一个可重现的:

static uint32_t volatile * volatile CurrentTaskStackPtr;
CurrentTaskStackPtr = (uint32_t *) 0x20000001;
__asm volatile("LDR R8, =%0" : : "i"(CurrentTaskStackPtr) );

此外,我试图避免更改任何"上下文"寄存器的状态,这就是我使用立即读取的原因.

我一直收到这样的错误:

warning: 'asm' operand 0 probably does not match constraints
  187 |         __asm volatile("LDR R8, =%0" : : "i"(CurrentTaskStackPtr) );

我试过使用不同的约束字符,但我对汇编还不够熟悉,无法取得任何进展,任何帮助都将不胜感激.

谢谢.

推荐答案

"i"(CurrentTaskStackPtr)要求将C变量的value作为立即数.只有当C变量是编译时常量(如uint32_t *const CurrentTaskStackPtr = ...)时,这才能起作用.但是您的变量是volatile(不同于指向volatile),所以即使启用了优化,您也禁止编译器通过赋值进行常量传播来生成"i"(0x20000001).

If you want the address, take the address, 100.


或者更好的做法是,让编译器为您提供R8中的地址,而不是将ldr伪指令放入ASM模板中,除非您需要控制它如何实现地址或其他什么.

    register void *tmp_r8 asm("r8");   // forces "r" constraints to pick R8.
    tmp_r8 = &CurrentTaskStackPtr;
    asm("..."
       : // outputs
       : "r"(tmp_r8)
       : "memory"  // presumably you're going to deref that pointer
    );

另请参见https://stackoverflow.com/tags/inline-assembly/infoARM inline asm: exit system call with value read from memory以获取如何编译的示例.

GCC手册(https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html)明确指出,寄存器ASM局部变量的only保证行为是为内联asm语句挑选指定的寄存器;not保证在任何其他时间使用该寄存器.

另请参见How can I indicate that the memory *pointed* to by an inline ASM argument may be used?,以了解为什么需要"memory"撞击机.也许最好使用它而不是伪输入/输出操作数;无论如何,您都不希望编译器试图围绕上下文切换进行优化.


正在try 进行上下文切换

您可能更适合将上下文切换函数编写为__attribute__((naked)),因此您不必担心编译器何时访问相对于堆栈指针的本地变量.官方不支持更改asm语句内的堆栈指针.(https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#index-asm-clobbers-拦截器列表不应包含堆栈指针.)

除了在naked函数中,您在一个基本的ASM语句中编写整个函数的ASM,它不能内联到任何调用方,因为它类似于__attribute__((noinline,noipa)),或者像是在单独的.s文件中编写它并只是定义一个原型.

C++相关问答推荐

为什么我得到更多的256假阳性在PKZIP解密密钥验证?

创建一个fork导致fget无限地重新读取文件

是否所有C编译器在将浮点数转换为整型数时都会隐式删除小数?

用C宏替换strncMP函数中的参数

在列表中插入Int指针(C)

以下声明和定义之间的区别

Square不与Raylib一起移动

如何使用_newindex数组我总是得到错误的参数

获取前2个连续1比特的索引的有效方法

C语言中MPI发送接收字符串时出现的分段错误

STM32 FATFS用户手册(Um1721)中的代码正确吗?

Linux/C:带有子进程的进程在添加waitid后都挂起

变量值不正确的问题

分配给静态变量和动态变量的位置之间有区别吗?

为什么<到达*时不会转换为>?

子进程不会修改父进程中的统计信息

为什么需要struct in_addr

返回指向函数内声明的复合文字的指针是否安全,还是应该使用 malloc?

我们可以在不违反标准的情况下向标准函数声明添加属性吗?

char* 上的 free() 被 valgrind 识别为无效