Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.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
`push label`push[label],而不是标签的地址(Rust asm!)_Rust_X86 64_Inline Assembly - Fatal编程技术网

`push label`push[label],而不是标签的地址(Rust asm!)

`push label`push[label],而不是标签的地址(Rust asm!),rust,x86-64,inline-assembly,Rust,X86 64,Inline Assembly,我正在写一个操作系统。我使用asm宏以更改代码段。(关于2020/06/08对asm!和中的更改的详细信息) pub不安全的fn集合码段(偏移量:u16){ asm!(“推送{0:r}//64位版本的寄存器 lea-rax,1f//或更有效,[rip+1f] 推拉 retfq 1:“,在(reg)偏移量中,”; } 这很有效。但是,如果我使用push 1f,标签1:的地址将不会被推送。相反,它将是一个内存源操作数,从[1://code> 所以下面的代码 pub不安全的fn集合码段(偏移量:u1

我正在写一个操作系统。我使用
asm宏以更改代码段。(关于2020/06/08对asm!
和中的更改的详细信息)

pub不安全的fn集合码段(偏移量:u16){
asm!(“推送{0:r}//64位版本的寄存器
lea-rax,1f//或更有效,[rip+1f]
推拉
retfq
1:“,在(reg)偏移量中,”;
}
这很有效。但是,如果我使用
push 1f
,标签
1:
的地址将不会被推送。相反,它将是一个内存源操作数,从
[1://code>

所以下面的代码

pub不安全的fn集合码段(偏移量:u16){
asm!(“推送{0:r}
push 1f//从1f加载,如何改为推送地址?
retfq
1:“,在(reg)偏移量中,”;
}
这是行不通的。反汇编(通过NDISAM
)代码如下:

11103   │ 0000B9EC  57                push rdi
11104   │ 0000B9ED  FF3425F6B90080    push qword [0xffffffff8000b9f6]
11105   │ 0000B9F4  48CB              retfq

用nasm语法编写的所需代码如下:

    [bits 64]

    extern set_code_segment

set_code_segment:
    push rdi
    push change_code_segment         ; absolute address as a 32-bit immediate
    retfq
change_code_segment:
    ret
与内核(和
extern“C”{pub fn set_code_段(偏移量_of_cs:u16)->()}
)链接,代码可以工作。将成功推送
change\u code\u段的地址


所以我的问题是:为什么
asm的
推1f
推送地址
1:
的内容,而不是
1:

的地址。
asm宏是基于
llvm
构建的

在llvm中,有人将仅由
0
1
数字组成的标签(如
0
11
101010
)解释为二进制值。这就是这里发生的事情,这个二进制值被读取为内存中的地址


还有,锈
asm文档已经更新,现在包含了一个。

AFAIK,Rust的内联汇编从GCC中获得了一些灵感。因此,您可能需要使用
$
前缀来指定您指的是立即操作数:
push$1f
@Michael谢谢您的评论,但是
push$1f
并没有改变这种情况。。。反汇编的代码是相同的。@PeterCordes
r
of
{0:r}
将寄存器的大小指定为64位。令我惊讶的是,使用16位寄存器会导致一般保护故障。我找到的文档明确表示,它应该使用GAS/LLVM样式的
。英特尔语法noprefix
,因此我认为这是一个
推送偏移1f
不起作用的错误。“我不确定报告此事的最佳地点。@PeterCordes感谢您提供了许多有用的意见。”。我发送了。关于github问题的评论建议使用
2:
可能是一种解决方法。但是我测试了(在一个独立的
.s
中,带有叮当声),并且。因此,我想使用
.Lfoobar:
并希望asm不会在同一个文件中扩展两次,或者在asm模板字符串中寻找与GCC内联asm的
%=
自动编号功能等效的生锈内联asm。