rust-playground 有一个遗憾是不支持 target 切换,compiler explorer 倒是可以切换
只不过我很好奇为什么 rustc --emit=asm 输出非常多的汇编代码而 playground/explorer 倒是很整洁只有用户定义的函数相应的汇编
于是我看了下原来 compiler explorer 的 filter 选项有过滤掉 unused labels 且 Output 选项有 demangle
再看看 playground 源码 demangle_asm() 函数 rust-playground/compiler/base/asm-cleanup/src/lib.rs
内部则是调用 rust-lang/rustc-demangle,试试看 demangle 效果首先我们先生成下汇编代码
rustc --emit=asm --crate-type=lib --target=riscv64gc-unknown-none-elf s.rs
#![no_std]
pub fn a(a: isize) -> isize {
fn b(b: isize) -> isize {
b
}
b(a)
}在 rust-playground 源码中写一个测试用例
#[test]
fn x() {
let code = std::fs::read_to_string("/home/w/temp/s.s").unwrap();
let code = demangle_asm(&code);
let code = filter_asm(&code);
println!("{code}");
}将 compiler explorer 默认选项输出为 intel 语法去掉,于是我们输出结果就跟 playgrond/explorer 完全一致了
s::a:
pushq %rax
callq s::a::b
// 悟了,rcx 在这里没啥用,只是随便找个寄存器存 pop 指令结果
popq %rcx
retq
s::a::b:
movq %rdi, %rax
retq
第一个整型参数会通过rdi寄存器传递
第二个整型参数会通过rsi寄存器传递
第三个整型参数会通过rdx寄存器传递
第四个整型参数会通过rcx寄存器传递
返回值在 rax
#include <stddef.h>
size_t b(const size_t b) { return b; }
size_t a(const size_t a) { return b(a); }b:
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov rax, QWORD PTR [rbp-8]
pop rbp
ret
a:
push rbp
mov rbp, rsp
sub rsp, 8
mov QWORD PTR [rbp-8], rdi
mov rax, QWORD PTR [rbp-8]
mov rdi, rax
call b
leave
ret