assembly - 从Rust更改x86中的执行堆栈

标签 assembly rust x86 inline-assembly

我正在尝试手动设置RSP并使用内联x86_64程序集在Rust中的自定义地址处开始执行。

我有这个C代码可以工作:

#include <stddef.h>

void __attribute ((noreturn)) jump_with_stack(size_t jump_addr, size_t *jump_stack) {
            __asm__ volatile ( \
                        "movq %[stack], %%rsp\n" \
                        "xor %%rdx, %%rdx\n" \
                        "jmp *%[entry]" \
                        : /* None  */ \
                        : [stack] "r" (jump_stack), [entry] "r" (jump_addr) \
                        : "rdx", "memory" \
                        );
}

这是反汇编:
jump_with_stack:
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], rdi
        mov     QWORD PTR [rbp-16], rsi
        mov     rax, QWORD PTR [rbp-16]
        mov     rcx, QWORD PTR [rbp-8]
        movq rax, %rsp
        xor %rdx, %rdx
        jmp *rcx
        nop
        pop     rbp
        ret

而且这个Rust代码不会:
#![feature(asm)]

pub unsafe extern fn rust_jump_with_stack(target: usize, targ_stack: *mut usize) -> ! {

    asm!("mov rsp, $0
         xor rdx, rdx
         jmp [$1]"
         :
         :"r"(targ_stack), "r"(target)
         : "rdx", "memory"
         : "intel");
    unreachable!();
}

这是除 rust 剂:
example::rust_jump_with_stack:
    push    rax

    mov     rsp, rsi
    xor     rdx, rdx
    jmp     qword ptr [rdi]

    lea     rdi, [rip + .L__unnamed_3]
    lea     rdx, [rip + .L__unnamed_4]
    mov     rax, qword ptr [rip + std::panicking::begin_panic@GOTPCREL]
    mov     esi, 40
    call    rax
    ud2

(两个拆卸输出均来自Godbolt资源管理器)

我不了解两者之间的区别,也不了解所生成代码的区别。

最佳答案

jmp [$1]是您在AT&T版本中没有的附加间接级别。

AT&T jmp *%1等效于Intel jmp %1

注意%[entry]只是写%1的一种象征性方式;方括号是操作数名称语法的一部分,并且不会以寻址模式语法结尾在最终的asm输出中。

(另外,您的问题是一团糟,因为在编写GNU C内联汇编以使用默认-masm=intel构建时,您在Godbolt上使用了-masm=att。)

其他主要区别在于,当您在启用优化的情况下构建Rust代码时,GCC默认为-O0(反优化 Debug模式)。

您可能应该在C __builtin_unreachable()语句之后使用asm(""),以确保编译器知道执行确实不会出现在asm语句的另一端。我担心标记包装函数noreturn可能不足以防止编译器假定它可以将存储推迟到内联之后的asm语句之后。 (跳出asm语句通常需要使用asm goto作为已知标签,否则建议使用__builtin_unreachable()。)

关于assembly - 从Rust更改x86中的执行堆栈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60251776/

相关文章:

rust - Iterator vs IntoIterator 用于扁平化

rust - 映射到没有克隆的载体上

程序集调用堆栈 - 术语问题

assembly - OR 指令汇编到 ECX 寄存器中

windows - 使用 IDA Pro 5 进行逆向工程简单应用程序

c++ - 使用 x64 汇编语言的通用 Windows 平台 C++

Rust 自定义可索引数据类型

x86 - 掩码向量英特尔 AVX-512 指令的汇编语法

c - 将 x86 程序下面的端口移植到 mips32

c - PIC10F200/202/204/206可以用什么语言编程?