【问题标题】:How can I call a rust function in rust inline asm module如何在 rust 内联 asm 模块中调用 rust 函数
【发布时间】:2022-08-21 13:26:01
【问题描述】:

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

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\",
);

它引发了链接时错误:

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
  • 在您的代码中,您不会将pt 用作extern \"C\",因此它的名称将被破坏并且它可能会采用不同的调用约定。
  • @PitaJ 我不认为这个问题是由于缺少 extern \"C\" 符号引起的。即使我添加了这个符号,编译器或链接器也会引发同样的错误。
  • 也许你有this 的问题?
  • 您还需要#[no_mangle]
  • @ChayimFriedman 非常感谢,代码可以用#[no_mangle]成功编译

标签: assembly rust inline-assembly


【解决方案1】:

默认情况下,Rust mangles 函数名称。 Rust 中名为 pt 的函数将命名为 _ZN7example2pt17hfba60a8558e697b1E 之类的名称,以说明 crate 名称、模块层次结构、特征和泛型参数 - 以防止名称冲突。因此链接器找不到它。

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

【讨论】:

    【解决方案2】:

    使用asm_sym feature,您可以调用损坏的函数名称:

    #![feature(asm_sym)]
    
    global_asm!(
        "
    .global myfunc
    myfunc:
    call {}
    ret",
    sym pt,
    );
    

    据我所知,这有望在 Rust 1.64.0 中稳定下来。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多