【问题标题】:`push label` pushs [label], not the address of label (Rust asm!)`push label` 推送 [label],而不是 label 的地址(Rust asm!)
【发布时间】:2020-11-09 08:51:33
【问题描述】:

我正在编写一个操作系统。我使用asm! 宏来更改代码段。 (2020/06/08 的详细信息更改为 asm! hereRust RFC 2873

pub unsafe fn set_code_segment(offset_of_cs: u16) {
    asm!("push {0:r}       // 64-bit version of the register
    lea rax, 1f            // or more efficiently, [rip + 1f]
    push rax
    retfq
    1:", in(reg) offset_of_cs);
}

这行得通。但是,如果我使用push 1f,标签1:的地址将不会被推送。相反,它将是一个内存源操作数,从[1:]加载

所以下面的代码

pub unsafe fn set_code_segment(offset_of_cs: u16) {
    asm!("push {0:r}
    push 1f           // loads from 1f, how to push the address instead?
    retfq
    1:", in(reg) offset_of_cs);
}

不会工作。反汇编(ndisasm)代码是这样的:

11103   │ 0000B9EC  57                push rdi
11104   │ 0000B9ED  FF3425F6B90080    push qword [0xffffffff8000b9f6]
11105   │ 0000B9F4  48CB              retfq

用 nasm 语法编写的所需代码是这样的:

    [bits 64]

    extern set_code_segment

set_code_segment:
    push rdi
    push change_code_segment         ; absolute address as a 32-bit immediate
    retfq
change_code_segment:
    ret

与内核(和extern "C" { pub fn set_code_segment(offset_of_cs: u16) -> () })链接,代码可以工作。 change_code_segment的地址将被成功推送。

所以我的问题是:为什么asm!push 1f推送地址1:的内容,而不是1:的地址?

【问题讨论】:

  • AFAIK,Rust 的内联汇编从 GCC 中汲取了一些灵感。因此,也许您需要使用 $ 前缀来指定您的意思是立即操作数:push $1f
  • @Michael 感谢您的评论,但push $1f 并没有改变这种情况...反汇编的代码是一样的。
  • @PeterCordes r of {0:r} 将寄存器的大小指定为 64 位。令我惊讶的是,使用 16 位寄存器会导致一般保护错误。
  • 我发现的文档明确说它应该使用 GAS / LLVM 样式 .intel_syntax noprefix,所以我认为这是一个错误 push OFFSET 1f 不起作用。我不确定报告的最佳地点。
  • @PeterCordes 感谢许多有用的 cmets。我发送了a bug report

标签: rust x86-64 inline-assembly


【解决方案1】:

rust asm! 宏是基于 llvm 构建的。

还有 llvm 中的 a specific bug 将仅由 01 数字组成的标签解释为二进制值,例如 011101010。这就是这里发生的事情,这个二进制值被读取为内存中的地址。

此外,rust asm! 文档已更新,现在包含 labels section

【讨论】:

  • 对该 github 问题的评论表明使用 2: 可能是一种解决方法。但我测试了(在一个独立的.s 和clang 中)和that doesn't work either。所以我想使用 .Lfoobar: 并希望你的 asm 不会在同一个文件中扩展两次,或者寻找与 GCC 内联 asm 的 %= 自动编号的东西等效的 Rust 内联 asm 来唯一化 asm 模板字符串中的东西。 Inline assembly label already defined error
猜你喜欢
  • 2014-05-13
  • 2019-08-26
  • 1970-01-01
  • 2012-07-02
  • 1970-01-01
  • 1970-01-01
  • 2020-08-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多