【发布时间】:2020-02-17 08:00:33
【问题描述】:
我将在下面的问题中写下我的假设(基于我的研究),我假设我的假设在问题本身之外存在错误:
我正在研究为 ARM 编写的一些代码:
这个函数(取自 FreeRTOS 端口代码):
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI(void)
{
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
__asm volatile(" mrs %0, basepri \n"
" mov %1, %2 \n"
" msr basepri, %1 \n"
" isb \n"
" dsb \n"
: "=r"(ulOriginalBASEPRI), "=r"(ulNewBASEPRI)
: "i"(configMAX_SYSCALL_INTERRUPT_PRIORITY));
/* This return will not be reached but is necessary to prevent compiler
warnings. */
return ulOriginalBASEPRI;
}
我在 gcc 中理解“=r”是输出操作数。所以我们将值从 asm 保存到 C 变量中
现在我理解的代码相当于:
ulOriginalBASEPRI = basepri
ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY
basepri = ulNewBASEPRI
我知道我们正在返回 BASEPRI 的原始值,所以这是第一行。但是,我不明白为什么我们分配变量 ulNewBASEPRI 然后我们在 MSR 指令中使用它..
所以我查看了ARMV7 instruction set,我看到了这个:
我假设拇指指令中没有(MSR 立即数),并且“编码 A1”意味着它仅在 Arm 指令模式下。 所以我们必须使用 =r 输出操作数让汇编器为我们的变量自动选择一个寄存器我正确吗?
编辑:忽略此部分,因为我记错了冒号
: "i"(configMAX_SYSCALL_INTERRUPT_PRIORITY));
根据我对assembly template的理解:
asm ( assembler template
: output operands /* optional */
: input operands /* optional */
: list of clobbered registers /* optional */
);
“i”在程序集中不只是表示(立即)或常量吗?
这是否意味着第三个冒号不仅用于clobber列表?
如果是这样,在输入操作数中找到约束“i”不是更合适吗?
编辑:忽略本节,因为我记错了冒号
我了解 isb,dsb 是内存屏障的东西,但我真的不明白它们的描述。他们到底在做什么? 例如,如果我们删除 dsb 或 isb 指令会发生什么?
【问题讨论】:
-
我想你可能记错了这里的冒号数。 “i”是一个输入。
ulOriginalBASEPRI和ulNewBASEPRI都出现在第一个冒号之后,因此是输出。configMAX_SYSCALL_INTERRUPT_PRIORITY出现在第二个冒号之后,输入也是如此。这个例子没有clobbers。 -
@DavidWohlferd,啊是的,我数错了!