如何在 Rust 内联 asm 模块中调用 Rust 函数

How can I call a rust function in rust inline asm module

我尝试像示例代码一样调用我的函数:

use std::arch::asm;

extern "C" fn foo(arg: i32) -> i32 {
    println!("arg = {}", arg);
    arg * 2
}

fn call_foo(arg: i32) -> i32 {
    unsafe {
        let result;
        asm!(
            "call *{}",
            // Function pointer to call
            in(reg) foo,
            // 1st argument in rdi
            in("rdi") arg,
            // Return value in rax
            out("rax") result,
            // Mark all registers which are not preserved by the "C" calling
            // convention as clobbered.
            clobber_abi("C"),
        );
        result
    }
} //this is the example code

我的代码:

use core::arch::global_asm;


fn main() {
    println!("Hello, world!");
    unsafe{
        myfunc();
    }
}

fn pt() {
    println!("This func is called by inline asm");
}

extern "C" {
    fn myfunc();
}
global_asm!(
    "   
.global myfunc
myfunc:
call *{}
ret",
in(reg) pt,
);

编译时报错

   Compiling asm_test v0.1.0 (/home/zhou/codes/rust/practice/asm_test)
error: expected expression, found keyword `in`
  --> src/main.rs:26:1
   |
26 | in(reg) pt,
   | ^^ expected expression

error: could not compile `asm_test` due to previous error

如果我尝试 call pt,像这样

use core::arch::global_asm;


fn main() {
    println!("Hello, world!");
    unsafe{
        myfunc();
    }
}

fn pt() {
    println!("This func is called by inline asm");
}

extern "C" {
    fn myfunc();
}
global_asm!(
    "   
.global myfunc
myfunc:
call pt
ret",
);

它引发 link 时间错误:

error: linking with `cc` failed: exit status: 1
  |
  = note: "cc" "-m64" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-cefff555edfd8301.asm_test.debf28cc-cgu.0.rcgu.o" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-cefff555edfd8301.asm_test.debf28cc-cgu.1.rcgu.o" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-cefff555edfd8301.asm_test.debf28cc-cgu.2.rcgu.o" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-cefff555edfd8301.asm_test.debf28cc-cgu.3.rcgu.o" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-cefff555edfd8301.asm_test.debf28cc-cgu.4.rcgu.o" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-cefff555edfd8301.asm_test.debf28cc-cgu.5.rcgu.o" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-cefff555edfd8301.asm_test.debf28cc-cgu.6.rcgu.o" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-cefff555edfd8301.asm_test.debf28cc-cgu.7.rcgu.o" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-cefff555edfd8301.4utlkaaskc2kqzwc.rcgu.o" "-Wl,--as-needed" "-L" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps" "-L" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,--start-group" "-Wl,-Bstatic" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-a46a068050a12a4b.rlib" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-1df56095db9453cb.rlib" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libminiz_oxide-9062de483386e50b.rlib" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libadler-b988ab269ff13602.rlib" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libobject-1bc822d886d4f7bd.rlib" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libmemchr-963eca8df4c224a6.rlib" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libaddr2line-d805b480c9102e58.rlib" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libgimli-06dfdbc22b935051.rlib" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd_detect-d7523a4d118e6572.rlib" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-5d7898c7fac3a07d.rlib" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libhashbrown-8c2bdbab4845bf3d.rlib" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-d578639df0547b30.rlib" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-58bbb7b1efa3a5e2.rlib" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcfg_if-4c9b082d197c16f8.rlib" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-70f9ed6d8e7a5ce6.rlib" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-8c0a241d0360fa53.rlib" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-bad7ed93fdd31371.rlib" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-98b4d121af2b7335.rlib" "-Wl,--end-group" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-1d9f7e5920635d15.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-znoexecstack" "-L" "/home/zhou/.rustup/toolchains/1.59.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-cefff555edfd8301" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro,-znow" "-nodefaultlibs"
  = note: /usr/bin/ld: /home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-cefff555edfd8301.asm_test.debf28cc-cgu.6.rcgu.o: in function `myfunc':
          asm_test.debf28cc-cgu.6:(.text+0x1): undefined reference to `pt'
          collect2: error: ld returned 1 exit status
          
  = help: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
  = note: use the `-l` flag to specify native libraries to link
  = note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)

warning: `asm_test` (bin "asm_test") generated 1 warning
error: could not compile `asm_test` due to previous error; 1 warning emitted

我的 rustc 版本是 rustc 1.59.0 (9d1b2106e 2022-02-23)

现在我想知道如何在内联 asm 中调用我的 rust 函数? 感谢您的回答。

ps:

即使我将extern "C"标记为pt()函数,它也会引发相同的错误。

通过函数指针调用:

use core::arch::global_asm;


fn main() {
    println!("Hello, world!");
    unsafe{
        myfunc();
    }
}

extern "C" fn pt() {
    println!("This func is called by inline asm");
}


extern "C" {
    fn myfunc();
}
global_asm!(
    "   
.global myfunc
myfunc:
call *{}
ret",
in(reg) pt,
);

输出:

   Compiling asm_test v0.1.0 (/home/zhou/codes/rust/practice/asm_test)
error: expected expression, found keyword `in`
  --> src/main.rs:25:1
   |
25 | in(reg) pt,
   | ^^ expected expression

error: could not compile `asm_test` due to previous error

直接通过函数名调用:

use core::arch::global_asm;


fn main() {
    println!("Hello, world!");
    unsafe{
        myfunc();
    }
}

extern "C" fn pt() {
    println!("This func is called by inline asm");
}


extern "C" {
    fn myfunc();
}
global_asm!(
    "   
.global myfunc
myfunc:
call pt
ret
"
);

产出

   Compiling asm_test v0.1.0 (/home/zhou/codes/rust/practice/asm_test)
warning: function is never used: `pt`
  --> src/main.rs:11:15
   |
11 | extern "C" fn pt() {
   |               ^^
   |
   = note: `#[warn(dead_code)]` on by default

error: linking with `cc` failed: exit status: 1
  |
  = note: "cc" "-m64" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-0ec3f71f4270eb6c.11cntnpkwkcxlijf.rcgu.o" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-0ec3f71f4270eb6c.1265vrgnblsvk7p4.rcgu.o" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-0ec3f71f4270eb6c.1t6teuukd293c2fa.rcgu.o" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-0ec3f71f4270eb6c.2dq4ncsizye722cr.rcgu.o" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-0ec3f71f4270eb6c.3wcrpa0pe60imxoq.rcgu.o" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-0ec3f71f4270eb6c.472oc353m17m7nk9.rcgu.o" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-0ec3f71f4270eb6c.4jq8ds1i0f9k3y80.rcgu.o" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-0ec3f71f4270eb6c.qpnijj966uqfsk9.rcgu.o" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-0ec3f71f4270eb6c.4jqwi4eladczupq3.rcgu.o" "-Wl,--as-needed" "-L" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps" "-L" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,--start-group" "-Wl,-Bstatic" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-8d61b92a0a02f53a.rlib" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-fc45202bb435016b.rlib" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libminiz_oxide-f2400674c7513725.rlib" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libadler-605c3a7d1a5d300d.rlib" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libobject-3d4fb4efa907e4e8.rlib" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libmemchr-65207f030ab23308.rlib" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libaddr2line-76ca199cb0186109.rlib" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libgimli-1e3e01ed4f561dc1.rlib" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-dd8dddcba7c13fee.rlib" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd_detect-00b13d31c3420656.rlib" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libhashbrown-e4c8460b81557bd5.rlib" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-600d46e5f0005455.rlib" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-e4a08a2585b62d37.rlib" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcfg_if-fbc21ec567cb9dc7.rlib" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-10b3fa8e49bd978f.rlib" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-64625b73694ffce7.rlib" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-fb6b78ac543a58ee.rlib" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-1d1f2d1bec6f51b8.rlib" "-Wl,--end-group" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-acf5ff6e9595d982.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-znoexecstack" "-L" "/home/zhou/.rustup/toolchains/1.60.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "/home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-0ec3f71f4270eb6c" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro,-znow" "-nodefaultlibs"
  = note: /usr/bin/ld: /home/zhou/codes/rust/practice/asm_test/target/debug/deps/asm_test-0ec3f71f4270eb6c.2dq4ncsizye722cr.rcgu.o: in function `myfunc':
          2dq4ncsizye722cr:(.text+0x1): undefined reference to `pt'
          collect2: error: ld returned 1 exit status
          
  = help: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
  = note: use the `-l` flag to specify native libraries to link
  = note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)

warning: `asm_test` (bin "asm_test") generated 1 warning
error: could not compile `asm_test` due to previous error; 1 warning emitted

默认情况下,Rust mangles 函数名称。 Rust 中名为 pt 的函数将被命名为类似 _ZN7example2pt17hfba60a8558e697b1E 的名称,以考虑 crate 名称、模块层次结构、特征和通用参数 - 以防止名称冲突。因此链接器无法找到它。

您可以使用 #[no_mangle] 属性命令 Rust 停止破坏特定函数。当心 this attribute is unsafe:它可能导致名称冲突,这是未定义的行为。此外,要从程序集中调用函数,您将需要一个定义的调用约定,例如extern "C".