assembly - 如何安全地传递最终传递到内联汇编的 IO 地址?
问题描述
我有一个 AVR 项目的简短程序集片段:
uint8_t high = _BV(0);
uint8_t low = ~high;
uint8_t port_value = 0;
asm volatile (
"in %0, %1 \n\t"
"or %0, %3 \n\t"
"out %1, %0 \n\t"
T1H_NOOP
"and %0, %2 \n\t"
"out %1, %0 \n\t"
T1L_NOOP
: "=r" (port_value)
: "I" (_SFR_IO_ADDR(PORTB)), "r" (low), "r" (high));
该块背后的想法是在短时间内启用特定引脚(实际的物理微处理器引脚)(T1H_NOOP),然后将其关闭。上面的代码实际上完美无缺。
但是,在上面的代码中,确切的引脚是硬编码的:PORTB,引脚 0 ( _BV(0)
)。我想要的是传递一个这样的地址:
struct IO_ADDR {
volatile uint8_t *port;
uint8_t pin
}
只要我保留在 C 代码中,这实际上是有效的。
struct IO_ADDR addr = { .port = &PORTB, .bit = 0 };
latch(&addr);
void latch(struct IO_ADDR *addr) {
if (addr->bit >= 8) return;
*(addr->port) &= ~(_BV(addr->bit));
_delay_us(50);
}
当我这么说的时候,我的意思是我已经通过模拟器运行了它,并且看到了引脚按预期启动,另外我已经将这个片段与上面的程序集配对并在硬件上运行它。所以,很明显,*(addr->port) &= ...
是寻址引脚本身,而不是指针。凉爽的。
但是当我这样做时,我得到一个装配错误:
asm volatile (
"in %0, %1 \n\t"
"or %0, %3 \n\t"
"out %1, %0 \n\t"
T1H_NOOP
"and %0, %2 \n\t"
"out %1, %0 \n\t"
T1L_NOOP
: "=r" (port_value)
: "I" (_SFR_IO_ADDR(*(addr->port))), "r" (low), "r" (high));
这个错误:
/nix/store/j31yaksw2dh82by2lgz1ysgh494cz6j2-src/neopixels.c: In function 'write_value':
/nix/store/j31yaksw2dh82by2lgz1ysgh494cz6j2-src/neopixels.c:29:9: warning: asm operand 1 probably doesn't match constraints
29 | asm volatile (
| ^~~
/nix/store/j31yaksw2dh82by2lgz1ysgh494cz6j2-src/neopixels.c:29:9: error: impossible constraint in 'asm'
如果我将 addr->port 参数替换为_SFR_IO_ADDR(addr->port)
.
SFR_IO_ADDR(*(addr->port))
对此进行预处理:
: "I" (
# 38 "src/neopixels.c" 3 4
(((uint16_t) &(
# 38 "src/neopixels.c"
*(addr->port)
# 38 "src/neopixels.c" 3 4
)) - 0x20)
# 38 "src/neopixels.c"
)
PORTB
在这个特定硬件上的地址为 0x24的情况下,最终的程序集应该是这样的(并且忽略编译器选择的确切寄存器):
in r18, 24
or r18, r21
out 24, r18
我需要做什么才能将该特定的 IO 地址传递给我的汇编代码?
解决方案
"I"
装配约束要求它的操作数是一个常数(或者,使用 -O1/-O2,一个常数表达式),所以很遗憾你不能将它作为参数传递。
推荐阅读
- docker - Docker 卷未安装在容器中
- laravel - 在 Laravel 中验证日期
- sharepoint - https://graph.microsoft.com/beta/sites?search=* 在测试版中被破坏
- google-kubernetes-engine - gke 作业容器重新启动
- android - 是否可以将状态栏图标颜色更改为白色?还是有深色主题状态栏?(科特林)
- python-3.x - 如何将 matplotlib 光标 mouse_move 对象与滑块值连接?
- javascript - 我如何在反应中修改 array.map 函数
- javascript - 为什么我收到 TypeError:无法读取未定义的属性“执行”
- c - 宏中的 Sizeof(SIMD 向量)问题
- jquery - 用`webpack`贴花的外部的角度`build`抛出错误