使用参数时内联汇编的混乱 [英] Inline assembly confusion when using parameters

查看:118
本文介绍了使用参数时内联汇编的混乱的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在x86_64 Linux上使用Rust的内联汇编功能.我编写了一个简单的程序,用值23调用exit syscall.

I'm experimenting with Rust's inline assembly feature on x86_64 Linux. I've written a simple program that calls the exit syscall with the value 23.

#![feature(asm)]

fn main() {
  unsafe {
    asm!(
      "
      mov $$60, %rax
      mov $$23, %rdi
      syscall
      "
      :
      :
      : "%rax", "%rdi"
    );
  }
}

该程序可以正常工作,我可以rustc exit.rs; ./exit; echo $?并获得23.现在,我想使生锈的asm代码接口.因此,我从锈中传入了23,而不是在程序集中对其进行硬编码.

This program works fine, I can rustc exit.rs; ./exit; echo $? and get 23. Now I want to make the asm code interface with rust. So I pass the 23 in from rust rather than hardcoding it in the assembly.

#![feature(asm)]

fn main() {
  unsafe {
    asm!(
      "
      mov $$60, %rax
      mov $0, %rdi
      syscall
      "
      :
      : "r"(23)
      : "%rax", "%rdi"
    );
  }
}

这再次起作用.现在,我尝试使用变量传递23.

Once again, this works. Now I try to pass 23 in using a variable.

#![feature(asm)]

fn main() {
  let x = 23i;
  unsafe {
    asm!(
      "
      mov $$60, %rax
      mov $0, %rdi
      syscall
      "
      :
      : "r"(x)
      : "%rax", "%rdi"
    );
  }
}

这打破了.它以60而不是23退出.查看生成的程序集将说明原因:

And this breaks. It exits with 60 rather than 23. Looking at the generated assembly shows why:

movq    $23, (%rsp)
movq    (%rsp), %rax
#APP

movq    $60, %rax
movq    %rax, %rdi
syscall

编译器尝试将23保存到%rax中,但随后内联汇编中的%rax被60覆盖.

The compiler tries to save 23 into %rax but then %rax gets overwritten by 60 in the inline assembly.

那么,这是一个编译器错误吗?还是我现在不怎么使用内联汇编? (后者很有可能).

So, is this a compiler bug? Or do I just not now how to use inline assembly? (The latter is quite possible).

根据请求,LLVM IR输出为:

As per request, the LLVM IR output is:

; ModuleID = 'exit.0.rs'
target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; Function Attrs: uwtable
define internal void @_ZN4main20h2dd3717eeddb6da6eaaE() unnamed_addr #0 {
entry-block:
  %x = alloca i64
  store i64 23, i64* %x
  %0 = load i64* %x
  call void asm "\0A      mov $$60, %rax\0A      mov $0, %rdi\0A      syscall\0A      ", "r,~{%rax},~{%rdi},~{dirflag},~{fpsr},~{flags}"(i64 %0), !srcloc !0
  ret void
}

define i64 @main(i64, i8**) unnamed_addr #1 {
top:
  %2 = call i64 @_ZN2rt10lang_start20h6ebacfb5a732c9b9PfyE(i8* bitcast (void ()* @_ZN4main20h2dd3717eeddb6da6eaaE to i8*), i64 %0, i8** %1)
  ret i64 %2
}

declare i64 @_ZN2rt10lang_start20h6ebacfb5a732c9b9PfyE(i8*, i64, i8**) unnamed_addr #1

attributes #0 = { uwtable "split-stack" }
attributes #1 = { "split-stack" }

!0 = metadata !{i32 21}

推荐答案

已解决,感谢github上的@pczarn.问题在于,应将便笺清单写为"rax", "rdi"而不是"%rax", "%rdi".

Solved, thanks to @pczarn on github. The issue was that the list of clobbers should be written "rax", "rdi" not "%rax", "%rdi".

这篇关于使用参数时内联汇编的混乱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆