Rust에서 #![no_std]의 "Hello, World!"을 시도하십시오.
8761 단어 Rust
환경
Linux Mint 20.1 Ulyssa
rustc 1.53.0 nightly-x86_64-unknown-linux-gnu
동기
낮은 레이어 소녀이라는 YouTube 채널에서 어셈블리에서 놀고있는 것을 보면 Rust
asm!
매크로로 어셈블리를 작성하려고합니다. 어셈블리는 초보자이므로 먼저 "Hello, World!"로 입문해 보겠습니다. 그리고, 이쪽의 「리눅스에서 no_std의 Rust on Hello, world!」라고 하는 기사를 참고로 했습니다. 이 기사에서는 참고 기사와는 다른 부분만 씁니다.진입점
링커에
-nostartfiles
옵션을 전달하고 _start
함수에 어셈블리를 작성합니다..cargo/config.toml
[build]
rustflags = ["-Clink-arg=-nostartfiles"]
main.rs
#![no_std]
#![no_main]
#[no_mangle]
fn _start() {
// ここにアセンブリを書いていく!
}
#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! {
loop {}
}
Segmentation fault는 발생하지만, 우선 실행할 수 있는 바이너리가 생겼습니다.
어셈블리 작성
#1: FizzBuzz를 어셈블리 언어로 쓰고 싶다!을 참고로 "Hello, World!"의 어셈블리를 작성해 보았습니다.
main.rs
#[no_mangle]
fn _start() {
unsafe {
asm!(
"mov rdx, 14",
"lea rsi, [string]",
"mov rdi, 1",
"mov rax, 1",
"syscall",
"mov rax, 60",
"syscall",
"string:",
".ascii \"Hello, World!\n\"",
);
}
}
그런데 이것은 링커가
relocation R_X86_64_32S against '.text._start' can not be used when making a PIE object; recompile with -fPIE
라는 에러를 토해 빌드에 실패했습니다. PIE
란 무엇입니까?Wiki에서 인용
위치 독립 코드(이치도리리트 코드, 영: position-independent code, PIC) 또는 위치 독립 실행 형식(이치도쿠리츠츠코 게이시키, 영: position-independent executable, PIE)이란, 주 기억 장치내의 어디에 둔 그래도 절대 주소에 관계없이 올바르게 실행할 수 있는 기계어의 열이다.
데이터 위치의 절대 주소, 상대 주소적인 것일까? (잘 모르겠다…) 어쨌든 링커 옵션에
-pie
가 붙여지고 있는 것이 원인같기 때문에 이것을 무효로 할 필요가 있습니다.그러기 위해서는 분명히
-Crelocation-model=dynamic-no-pic
라는 옵션을 rustc 에 건네주면 좋을 것 같습니다.cargo/config.toml
[build]
rustflags = ["-Clink-arg=-nostartfiles", "-Crelocation-model=dynamic-no-pic"]
이제 무사히 빌드 실행할 수 있었습니다. 했어
덧붙여서 문자열의 주소를 rip 상대
lea rsi, [rip + string]
로 해 주면-Crelocation-model=dynamic-no-pic
는 불필요했습니다.rustc에 어셈블리를 뱉어내기
rustc에 어셈블리를 뱉게 하려면 다음과 같이 하십시오. (intel 기법의 경우)
cargo rustc --release -- --emit asm -Cllvm-args=-x86-asm-syntax=intel
.cargo/config.toml
에 alias 로 설정해 두면 즐거웠다고 생각합니다. 아래와 같이 쓰면cargo asm
명령으로 어셈블리가 출력됩니다..cargo/config.toml
[alias]
asm = "rustc --release -- --emit asm -Cllvm-args=-x86-asm-syntax=intel"
어셈블리는
target/release/deps/*.s
로 출력됩니다. 내용을 들여다 보면 #APP
와 #NOAPP
사이에 asm!
매크로의 설명이 그대로 출력되었습니다._start:
sub rsp, 8
#APP
mov rdx, 14
lea rsi, [string]
mov rdi, 1
mov rax, 1
syscall
mov rax, 60
syscall
string:
.ascii "Hello, World!\n"
#NO_APP
pop rax
ret
아티팩트
Cargo.toml
[package]
name = "hello_from_asm"
version = "0.1.0"
authors = ["benki"]
edition = "2018"
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
.cargo/config.toml
[alias]
asm = "rustc --release -- --emit asm -Cllvm-args=-x86-asm-syntax=intel"
[build]
rustflags = ["-Clink-arg=-nostartfiles", "-Crelocation-model=dynamic-no-pic"]
main.rs
#![no_std]
#![no_main]
#![feature(asm)]
#[no_mangle]
fn _start() {
unsafe {
asm!(
"mov rdx, 14",
"lea rsi, [string]",
"mov rdi, 1",
"mov rax, 1",
"syscall",
"mov rax, 60",
"syscall",
"string:",
".ascii \"Hello, World!\n\"",
);
}
}
#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! {
loop {}
}
Reference
이 문제에 관하여(Rust에서 #![no_std]의 "Hello, World!"을 시도하십시오.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/benki/items/74bdc421ec7d9fdc123a텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)