assembly - 如何将 AVR GCC 风格的 C 内联汇编翻译成 Rust 内联汇编?
问题描述
我想将一些最初用 C++ 编写的 Arduino 代码翻译成 Rust,但是这行内联汇编给我带来了麻烦。
asm volatile(
" lds r16, %[timer0] \n\t" //
#if defined(__AVR_ATmega2560__)
" add r16, %[toffset] \n\t" //
#endif
" subi r16, %[tsync] \n\t" //
" andi r16, 7 \n\t" //
" call TL \n\t" //
"TL: \n\t" //
#if defined(__AVR_ATmega2560__)
" pop r17 \n\t" //ATMEGA2560 has a 22bit PC!
#endif
" pop r31 \n\t" //
" pop r30 \n\t" //
" adiw r30, (LW-TL-5) \n\t" //
" add r30, r16 \n\t" //
//" adc r31, __zero_reg__ \n\t" //
" ijmp \n\t" //
"LW: \n\t" //
" nop \n\t" //
" nop \n\t" //
" nop \n\t" //
" nop \n\t" //
" nop \n\t" //
" nop \n\t" //
" nop \n\t" //
//" nop \n\t" //
"LBEND: \n\t" //
:
: [timer0] "i" (&TCNT0),
[toffset] "i" ((uint8_t)DEJITTER_OFFSET),
[tsync] "i" ((uint8_t)DEJITTER_SYNC)
: "r30", "r31", "r16", "r17");
我最好的尝试是这样的:
const TCNT0: *mut u8 = 70 as *mut u8;
const DEJITTER_OFFSET: u8 = 1;
const DEJITTER_SYNC: i8 = -2;
asm!(
" lds r16, %[timer0]
\t subi r16, %[tsync]
\t andi r16, 7
\t call TL
\tTL:
\t pop r31
\t pop r30
\t adiw r30, (LW-TL-5)
\t add r30, r16
\t ijmp
\tLW:
\t nop
\t nop
\t nop
\t nop
\t nop
\t nop
\t nop
\tLBEND:
\t"
:
: "{timer0}"(&TCNT0),
"{toffset}"(DEJITTER_OFFSET),
"{tsync}"(DEJITTER_SYNC)
: "r30", "r31", "r16": "volatile");
我离编译还差得很远。我尝试编译时显示的错误是:
error: couldn't allocate input reg for constraint '{timer0}'
--> /home/kirbylife/Proyectos/rvgax/src/lib.rs:53:9
|
53 | / asm!(
54 | | r" lds r16, ${timer0}
55 | | subi r16, ${tsync}
56 | | andi r16, 7
... |
77 | | "{tsync}"(DEJITTER_SYNC)
78 | | : "r30", "r31", "r16": "volatile");
| |_______________________________________^
我正在使用 Cargo 和 rustc 1.38.0。
解决方案
您的错误的直接含义是没有称为timer0
,toffset
和的寄存器tsync
。根本原因是"{}"
Rust 中的语法表示约束的寄存器名称,而不是符号名称。换句话说,它对应""
于 GCC 中的东西,而不是[]
东西。我看不到使用符号名称的方法,因此只需切换到数字名称即可。此外,它使用$
而不是%
替换约束。试试这个:
const TCNT0: *mut u8 = 70 as *mut u8;
const DEJITTER_OFFSET: u8 = 1;
const DEJITTER_SYNC: i8 = -2;
asm!(
" lds r16, $0
\t subi r16, $2
\t andi r16, 7
\t call TL
\tTL:
\t pop r31
\t pop r30
\t adiw r30, (LW-TL-5)
\t add r30, r16
\t ijmp
\tLW:
\t nop
\t nop
\t nop
\t nop
\t nop
\t nop
\t nop
\tLBEND:
\t"
:
: "i"(&TCNT0),
"i"(DEJITTER_OFFSET),
"i"(DEJITTER_SYNC)
: "r30", "r31", "r16": "volatile");
(注意:未经测试,因为我目前没有安装 AVR-Rust)
推荐阅读
- python - (Windows 10)无法使用 Anaconda 提示 - AttributeError:模块“colorama”没有属性“init”
- javascript - javascript:我的 appendChild 只工作一次
- assembly - 如何使用 DPMI 将内存分配给特定的虚拟地址?
- numpy - 查找参数样条曲线和直线之间的交点
- python - AttributeError:当应用 Global MaxPooling 而不是 GlobalAveragePooling 时,“Tensor”对象没有属性“lower”
- python - 有没有办法在情节中添加到图像的超链接?
- apache-spark - 无法运行示例,错误“-Xmx1g org.apache.spark.deploy.SparkSubmit”
- swift - ViewDidLoad 中与 CoreData 相关的崩溃
- google-apps-script - Google Spreadsheets ArrayFormula:如何拆分和转置单元格范围?
- ansible - ansible include_tasks 忽略标签