如何为Rust中的ARM芯片的堆栈指针赋值?

ter*_*ret 5 embedded rust

我正在尝试为Rust中的STM32编写一个bootloader,我无法弄清楚如何正确填充堆栈指针.我可以告诉代码应该是:

asm!("MOV SP, $0" :: "0"(stack_pointer));  // set the stack pointer
Run Code Online (Sandbox Code Playgroud)

但是编译器不同意:

error: invalid operand in inline asm: 'MOV SP, $0'
  --> src/main.rs:38:5
   |
38 |     asm!("MOV SP, $0" :: "0"(stack_pointer));  // set the stack pointer
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: <inline asm>:1:11: error: unexpected token in operand
        MOV SP, 
                ^

  --> src/main.rs:38:5
   |
38 |     asm!("MOV SP, $0" :: "0"(stack_pointer));  // set the stack pointer
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?它似乎在抱怨美元符号,但我直接从文档中得到了它.

根据评论中的对话,我尝试了两件事,两者都编译(!),但两者似乎都没有用(但这可能是十亿个原因中的任何一个,仍在继续):

版本A:

asm!("MOV R0, #0x0800");
asm!("LSL R0, R0, #16");
asm!("MOV R1, #0x8000");
asm!("ORR R2, R1, R0");
asm!("LDRT R0, [R2]");
asm!("MOV SP, R0");
entry_point()
Run Code Online (Sandbox Code Playgroud)

版本B:

#[inline(never)]
unsafe fn go(_addr: u32, entry_point: fn()->()) {
    asm!("MOV SP, R0");
    entry_point()
}
Run Code Online (Sandbox Code Playgroud)

Ste*_*fan 3

在我看来你有两个问题:

  1. 弄清楚汇编代码最终应该是什么样子
  2. 如何从 Rust 构建它。

第二部分看起来很简单global_asm!

#![feature(global_asm)]

global_asm!(r#"
.global go
go:
    mov sp, r0
    bx r1
"#);
extern "C" {
    pub fn go(addr: u32, entry_point: extern fn());
}
Run Code Online (Sandbox Code Playgroud)

或正常asm!

#![feature(asm)]

#[no_mangle]
pub unsafe fn go(addr: u32, entry_point: fn()) {
    asm!("mov sp, r0" :: "{r0}"(addr) : "sp");
    entry_point()
}
Run Code Online (Sandbox Code Playgroud)

我认为这"0"(stack_pointer)部分不起作用,因为stack_pointer它不是一个常数。

您的版本 B 会产生相同的 ASM 代码;但它确实应该将“sp”标记为已损坏,并"{r0}"(addr)确保第一个参数确实位于r0.

Clifford似乎更喜欢传递指向“向量表”的指针,它可能如下所示:

#[repr(C)]
pub struct VectorTable {
    stack_pointer: u32,
    entry_point: extern fn() -> !,
}

global_asm!(r#"
.global go
go:
    ldr sp, [r0]
    ldr pc, [r0, #4]
"#);
extern "C" {
    pub fn go(vt: &VectorTable) -> !;
}
Run Code Online (Sandbox Code Playgroud)