tomoyuki-nakabayashi / Rustemu86

Apache License 2.0
5 stars 0 forks source link

初めてのRust実行 #14

Closed tomoyuki-nakabayashi closed 6 years ago

tomoyuki-nakabayashi commented 6 years ago

スタートアップルーチンを自分で書いてRustの関数を呼び出す。

tomoyuki-nakabayashi commented 6 years ago

先にC言語でやるのも良いかもしれない?

tomoyuki-nakabayashi commented 6 years ago

https://os.phil-opp.com/set-up-rust/

ここを参考にベアメタルバイナリを作る。

tomoyuki-nakabayashi commented 6 years ago
rustup override add nightly
tomoyuki-nakabayashi commented 6 years ago

うんうん、できている。

build/hello-x86_64.bin:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <start>:
   0:   b8 00 00 00 00          mov    $0x0,%eax
   5:   e9 06 00 00 00          jmpq   10 <rust_main>
   a:   f4                      hlt
   b:   90                      nop

Disassembly of section .text.rust_main:

0000000000000010 <rust_main>:
  10:   eb 00                   jmp    12 <rust_main+0x2>
  12:   eb fe                   jmp    12 <rust_main+0x2>
#![feature(panic_implementation)]
#![no_std]

#[no_mangle]
pub extern fn rust_main() {
  loop{}
}

use core::panic::PanicInfo;

#[panic_implementation]
#[no_mangle]
pub fn panic(_info: &PanicInfo) -> ! {
    loop {}
}
tomoyuki-nakabayashi commented 6 years ago
  12:   eb fe                   jmp    12 <rust_main+0x2>

よく見たら、アドレス-2しているな。今unsignedしか対応していない気がする。直さないと。

tomoyuki-nakabayashi commented 6 years ago

Rust関数を空にすると、↓のようになる。

0000000000000010 <rust_main>:
  10:   c3                      retq

帰って来ようとするとretが必要か。まぁそりゃそうか。

tomoyuki-nakabayashi commented 6 years ago

にしても、ずいぶんもったいない使い方しているな。オブジェクトファイルが異なるから仕方ないのか?

   5:   e9 06 00 00 00          jmpq   10 <rust_main>
tomoyuki-nakabayashi commented 6 years ago

とりあえずjmpqを実装すればRustが呼べる。

tomoyuki-nakabayashi commented 6 years ago
#[no_mangle]
pub extern fn rust_main() {
  unsafe {
    asm!("mov rax, 0x10000000" :::: "intel");
  }
}
  10:   48 c7 c0 00 00 00 10    mov    $0x10000000,%rax

nasmでやるとターゲットをraxにしても、eax相当の命令が発行されているな。 Movも作り直さないとダメか。

tomoyuki-nakabayashi commented 6 years ago
ndisasm -b 64 filename

でdisassembleできる。

tomoyuki-nakabayashi commented 6 years ago

mov, jmpq, hltを実装すると、とりあえずRustを動かせる。 欲を言うと、callとretも欲しい。

tomoyuki-nakabayashi commented 6 years ago

nasmのバイナリ出力が変(というか最適化されてしまう)なので、llvm-asの利用を考える。

これでintelのシンタックスが使える。

  -x86-asm-syntax                                 - Choose style of code to emit from X86 backend:
    =att                                          -   Emit AT&T-style assembly
    =intel                                        -   Emit Intel-style assembly

と思ったが、llvmの中間表現が入力なのかー。うーむ。

tomoyuki-nakabayashi commented 6 years ago

https://stackoverflow.com/questions/48596247/why-nasm-on-linux-changes-registers-in-x86-64-assembly

なるほど。strictを付けると最適化を防げると。

tomoyuki-nakabayashi commented 6 years ago

確かに、最適化されていない。これで行こう。

$ cat simple_add.asm 
bits 64

mov rax, strict 1
mov rcx, 2
mov rdx, 0
mov rbx, 0
inc rcx
add rax, rcx
hlt

$ nasm simple_add.asm
$ ndisasm -b 64 simple_add
00000000  48B8010000000000  mov rax,0x1
         -0000
0000000A  B902000000        mov ecx,0x2
0000000F  BA00000000        mov edx,0x0
00000014  BB00000000        mov ebx,0x0
00000019  48FFC1            inc rcx
0000001C  4801C8            add rax,rcx
0000001F  F4                hlt
tomoyuki-nakabayashi commented 6 years ago

とりあえず、modrmを使うmovと、jmpqを作ってRustの関数を動かそう。

tomoyuki-nakabayashi commented 6 years ago

最終的に、ModRmを使うmovとcall/retを実装した。

https://github.com/tomoyuki-nakabayashi/baremetal_hello_in_rust

のRustインラインアセンブラからHelloが出力された!やったぜ!