x86_64 Linux에서 Rust의 인라인 어셈블리 기능을 실험하고 있습니다. 나는 값이 프로그램이 잘 작동 (23)매개 변수를 사용할 때 인라인 어셈블리 혼동
#![feature(asm)]
fn main() {
unsafe {
asm!(
"
mov $$60, %rax
mov $$23, %rdi
syscall
"
:
:
: "%rax", "%rdi"
);
}
}
, 내가 rustc exit.rs; ./exit; echo $?
23가 지금은 녹과 ASM 코드 인터페이스를 만들고 싶어 얻을 수로 exit
콜을 호출하는 간단한 프로그램을 작성했습니다. 그래서 나는 어셈블리에서 하드 코드하기보다는 녹이기에서 23을 전달합니다.
#![feature(asm)]
fn main() {
unsafe {
asm!(
"
mov $$60, %rax
mov $0, %rdi
syscall
"
:
: "r"(23)
: "%rax", "%rdi"
);
}
}
다시 한 번,이 작동합니다. 이제 변수 사용에 23을 전달하려고합니다.
#![feature(asm)]
fn main() {
let x = 23i;
unsafe {
asm!(
"
mov $$60, %rax
mov $0, %rdi
syscall
"
:
: "r"(x)
: "%rax", "%rdi"
);
}
}
그리고 이것은 깨집니다.
이movq $23, (%rsp)
movq (%rsp), %rax
#APP
movq $60, %rax
movq %rax, %rdi
syscall
컴파일러는 %rax
에 23을 저장하려고하지만 %rax
가 인라인 어셈블리 (60)에 의해 덮어 쓰기됩니다 : 왜 60이 아니라 23이 생성 된 어셈블리를 보면서로 종료를 보여줍니다.
그래서 이건 컴파일러 버그입니까? 또는 인라인 어셈블리를 사용하는 방법을 지금 막 모르겠습니다? (후자는 가능합니다).
편집 : 요청에 따라, LLVM IR 출력은 다음과 같습니다
해결; 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}
해체 된 LLVM IR을 게시 해주십시오. 그것은 문제 진단에 도움이 될 것입니다. – Maz
나는 '녹'을 말하지 않는다. 그러나 gm (asm과 비슷한 형식을 사용함)에서 clobbers로 rax와 rdi를 지정하면 매개 변수에 사용할 레지스터로 선택되지 않습니다. 실제로, gcc의 문서에 따르면'Clobber 설명이 입력 또는 출력 피연산자와 중복되지 않을 수도 있습니다 .' 녹이 gcc가 아니기 때문에 나는 버그라고 말할 수는 없지만 gcc에서는 제약 조건을 사용하려고합니다. ''(60),''(x)'와 같이 문자열을''syscall''으로 변경하십시오. FWIW. –