Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 从Rust更改x86中的执行堆栈_Assembly_Rust_X86_Inline Assembly - Fatal编程技术网

Assembly 从Rust更改x86中的执行堆栈

Assembly 从Rust更改x86中的执行堆栈,assembly,rust,x86,inline-assembly,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

我正在尝试手动设置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" \
                        );
}
该防锈代码不:

#![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!();
}
以下是除锈程序:

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
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
(两个拆解输出均来自导栓资源管理器)


我不理解两者之间的区别,也不理解生成的代码中的区别意味着什么

jmp[$1]
是AT&t版本中没有的额外间接寻址级别

AT&T
jmp*%1
相当于英特尔
jmp%1

请注意,
%[entry]
只是一种符号化的书写方式
%1
;方括号是操作数名称语法的一部分,不会作为寻址模式语法出现在最终asm输出中

(另外,您的问题完全是一团糟,因为您在Godbolt上使用了
-masm=intel
,而您的GNU C内联asm是用默认的
-masm=att
构建的)


另一个主要区别是GCC默认为
-O0
(反优化调试模式),而您构建的代码启用了优化



您可能应该在C
asm(“”
语句)之后使用
\u builtin\u unreachable()。我担心标记包装函数
noreturn
可能不足以防止编译器假定它可以将存储延迟到asm语句之后、内联之后。(跳出
asm
语句通常要求已知标签使用
asm goto
,否则建议使用
\uuuuuu builtin\u unreachable()

由于您指定了英特尔语法,第一个
mov
被颠倒。看起来您编译的锈迹代码启用了优化,但C使用了
gcc-O0
。这可能是两个编译器的默认值
-O0
是GCC的默认值。您可能希望在asm语句之后使用
\uuuuuu attribute\uuuuuuuuu((noinline))
\uuuuu buildin\u unreachable()
,以确保C函数不能以不安全的方式内联到调用方。我不确定在包装器函数上放置
noreturn
是否足够。不过,您仍然在asm模板中使用AT&T语法
jmp*%rcx
是AT&T版本的
jmp rcx
。您正在RDX上使用
%
装饰。在英特尔语法中,应使用xor edx,edx
将RDX归零。另外,如果您有一个指向指针的指针,您希望
jmp*([entry])
与您的Rust匹配,或者告诉编译器为您取消对它的引用。e、 g.
“rm”(*跳转地址)
对于
无效**跳转地址
。无论如何,尝试Godbolt上的二进制模式,将其实际组装为机器代码,然后进行反汇编,而不是仅仅进行内联asm文本替换,而不显示它甚至会进行组装。哦,然后更改Rust版本以匹配C版本,通过使用
jmp$1
匹配AT&T
jmp*%1
来消除额外的间接级别。在AT&T中,
[entry]
是操作数名称语法的一部分,而不是寻址模式的一部分。