2014-12-21 2 views
4

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} 
+0

해체 된 LLVM IR을 게시 해주십시오. 그것은 문제 진단에 도움이 될 것입니다. – Maz

+0

나는 '녹'을 말하지 않는다. 그러나 gm (asm과 비슷한 형식을 사용함)에서 clobbers로 rax와 rdi를 지정하면 매개 변수에 사용할 레지스터로 선택되지 않습니다. 실제로, gcc의 문서에 따르면'Clobber 설명이 입력 또는 출력 피연산자와 중복되지 않을 수도 있습니다 .' 녹이 gcc가 아니기 때문에 나는 버그라고 말할 수는 없지만 gcc에서는 제약 조건을 사용하려고합니다. ''(60),''(x)'와 같이 문자열을''syscall''으로 변경하십시오. FWIW. –

답변

3

, 감사 GitHub의에 @pczarn 할 수 있습니다. 문제는 청소부의 명단이 이 아닌 "%rax", "%rdi"으로 작성되어야한다는 것입니다.

관련 문제