mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-17 06:47:49 +00:00
computer-builtins-mem -> compiler-builtins-mem
Learning a lot from this blog. Thank you ð±
502 lines
45 KiB
Markdown
502 lines
45 KiB
Markdown
+++
|
||
title = "Rustã§ã€ããæå°ã®ã«ãŒãã«"
|
||
weight = 2
|
||
path = "ja/minimal-rust-kernel"
|
||
date = 2018-02-10
|
||
|
||
[extra]
|
||
chapter = "Bare Bones"
|
||
# Please update this when updating the translation
|
||
translation_based_on_commit = "7212ffaa8383122b1eb07fe1854814f99d2e1af4"
|
||
# GitHub usernames of the people that translated this post
|
||
translators = ["woodyZootopia", "JohnTitor"]
|
||
+++
|
||
|
||
ãã®èšäºã§ã¯ãRustã§æå°éã®64bitã«ãŒãã«ãäœããŸããåã®èšäºã§äœã£ã[ããªãŒã¹ã¿ã³ãã£ã³ã°ãªRustãã€ããª][freestanding Rust binary]ãäžæ·ãã«ããŠãäœããç»é¢ã«åºåãããããŒã¿ãã«ãã£ã¹ã¯ã€ã¡ãŒãžãäœããŸãã
|
||
|
||
[freestanding Rust binary]: @/edition-2/posts/01-freestanding-rust-binary/index.ja.md
|
||
|
||
<!-- more -->
|
||
|
||
ãã®ããã°ã®å
容㯠[GitHub] äžã§å
¬éã»éçºãããŠããŸããäœãåé¡ã質åãªã©ãããã° issue ãããŠãŠãã ãã (蚳泚: ãªã³ã¯ã¯åæ(è±èª)ã®ãã®ã«ãªããŸã)ããŸã[ãã¡ã][at the bottom]ã«ã³ã¡ã³ããæ®ãããšãã§ããŸãããã®èšäºã®å®å
šãªãœãŒã¹ã³ãŒãã¯[`post-02` ãã©ã³ã][post branch]ã«ãããŸãã
|
||
|
||
[GitHub]: https://github.com/phil-opp/blog_os
|
||
[at the bottom]: #comments
|
||
[post branch]: https://github.com/phil-opp/blog_os/tree/post-02
|
||
|
||
<!-- toc -->
|
||
|
||
## <ruby>èµ·å<rp> (</rp><rt>Boot</rt><rp>) </rp></ruby>ã®ããã»ã¹
|
||
ã³ã³ãã¥ãŒã¿ãèµ·åãããšããã¶ãŒããŒãã® [ROM] ã«ä¿åããããã¡ãŒã ãŠã§ã¢ã®ã³ãŒããå®è¡ãå§ããŸãããã®ã³ãŒãã¯ã[<ruby>èµ·åæã®èªå·±ãã¹ã<rp> (</rp><rt>power-on self test</rt><rp>) </rp></ruby>][power-on self-test]ãå®è¡ãã䜿çšå¯èœãªRAMãæ€åºããCPUãšããŒããŠã§ã¢ã<ruby>äºååæå<rp> (</rp><rt>pre-initialize</rt><rp>) </rp></ruby>ããŸãããã®åŸã<ruby>ããŒã¿ãã«<rp> (</rp><rt>bootable</rt><rp>) </rp></ruby>ãã£ã¹ã¯ãæ¢ãããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®ã«ãŒãã«ã<ruby>èµ·å<rp> (</rp><rt>boot</rt><rp>) </rp></ruby>ããŸãã
|
||
|
||
[ROM]: https://ja.wikipedia.org/wiki/Read_only_memory
|
||
[power-on self-test]: https://ja.wikipedia.org/wiki/Power_On_Self_Test
|
||
|
||
x86ã«ã¯2ã€ã®ãã¡ãŒã ãŠã§ã¢ã®æšæºèŠæ ŒããããŸãïŒ"Basic Input/Output System" (**[BIOS]**) ãšãããæ°ãã "Unified Extensible Firmware Interface" (**[UEFI]**) ã§ããBIOSèŠæ Œã¯å€ãæä»£é
ãã§ãããã·ã³ãã«ã§ãããã¹ãŠã®x86ã®ãã·ã³ã§1980幎代ãããããµããŒããããŠããŸãã察ããŠãUEFIã¯ããçŸä»£çã§ãã£ãšå€ãã®æ©èœãæã£ãŠããŸãããã»ããã¢ãããè€éã§ãïŒå°ãªããšãç§ã¯ããæããŸãïŒã
|
||
|
||
[BIOS]: https://ja.wikipedia.org/wiki/Basic_Input/Output_System
|
||
[UEFI]: https://ja.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface
|
||
|
||
ä»ã®æããã®ããã°ã§ã¯BIOSãããµããŒãããŠããŸããããUEFIã®ãµããŒããèšç»äžã§ãããæäŒãããã ããå Žåã¯ã[GitHubã®issue](https://github.com/phil-opp/blog_os/issues/349)ãã芧ãã ããã
|
||
|
||
### BIOSã®èµ·å
|
||
ã»ãŒãã¹ãŠã®x86ã·ã¹ãã ãBIOSã«ããèµ·åããµããŒãããŠããŸããããã¯è¿å¹Žã®UEFIããŒã¹ã®ãã·ã³ãäŸå€ã§ã¯ãªãããããã¯ãšãã¥ã¬ãŒããããBIOSã䜿ããŸããåäžçŽã®ãã¹ãŠã®ãã·ã³ã«ãåãããŒãããžãã¯ã䜿ãããªããŠçŽ æŽãããã§ããããããããã®åºãäºææ§ã¯ãBIOSã«ããèµ·åã®æå€§ã®æ¬ ç¹ã§ãããã®ã§ãããšããã®ãããã¯ã1980幎代ã®åç³ã®ãããªããŒãããŒããŒãåããããã«ãCPUã[<ruby>ãªã¢ã«ã¢ãŒã<rp> (</rp><rt>real mode</rt><rp>) </rp></ruby>][real mode]ãšåŒã°ãã16bitäºæã¢ãŒãã«ãããŠããŸããšããããšãæå³ããŠããããã§ãã
|
||
|
||
ãŸãé ã远ã£ãŠèŠãŠããããšãšããŸãããã
|
||
|
||
ã³ã³ãã¥ãŒã¿ã¯èµ·åæã«ãã¶ãŒããŒãã«ããç¹æ®ãªãã©ãã·ã¥ã¡ã¢ãªããBIOSãèªã¿èŸŒã¿ãŸããBIOSã¯èªå·±ãã¹ããšããŒããŠã§ã¢ã®åæåã«ãŒãã³ãå®è¡ããããŒã¿ãã«ãã£ã¹ã¯ãæ¢ããŸãããã£ã¹ã¯ãèŠã€ãããšã **<ruby>ããŒãããŒããŒ<rp> (</rp><rt>bootloader</rt><rp>) </rp></ruby>** ãšåŒã°ããããã®å
é 512ãã€ãã«ä¿åãããå®è¡å¯èœã³ãŒããžãšæäœæš©ãç§»ããŸããå€ãã®ããŒãããŒããŒã®ãµã€ãºã¯512ãã€ããã倧ãããããéåžžã¯512ãã€ãã«åãŸãå°ããªæåã®ã¹ããŒãžãšããã®æåã®ã¹ããŒãžã«ãã£ãŠèªã¿èŸŒãŸãã第2ã¹ããŒãžã«åããããŠããŸãã
|
||
|
||
ããŒãããŒããŒã¯ãã£ã¹ã¯å
ã®ã«ãŒãã«ã€ã¡ãŒãžã®å Žæãç¹å®ããã¡ã¢ãªã«èªã¿èŸŒãŸãªããã°ãªããŸããããŸããCPUã16bitã®[ãªã¢ã«ã¢ãŒã][real mode]ãã32bitã®[<ruby>ãããã¯ãã¢ãŒã<rp> (</rp><rt>protected mode</rt><rp>) </rp></ruby>][protected mode]ãžããããŠ64bitã®[<ruby>ãã³ã°ã¢ãŒã<rp> (</rp><rt>long mode</rt><rp>) </rp></ruby>][long mode]ââ64bitã¬ãžã¹ã¿ãšãã¹ãŠã®ã¡ã€ã³ã¡ã¢ãªãå©çšå¯èœã«ãªããŸãââãžãšå€æŽããªããã°ãªããŸããã3ã€ç®ã®ä»äºã¯ãç¹å®ã®æ
å ±ïŒäŸãã°ã¡ã¢ãªãŒããããªã©ã§ãïŒãBIOSããèãåºããOSã®ã«ãŒãã«ã«æž¡ãããšã§ãã
|
||
|
||
[real mode]: https://ja.wikipedia.org/wiki/ãªã¢ã«ã¢ãŒã
|
||
[protected mode]: https://ja.wikipedia.org/wiki/ãããã¯ãã¢ãŒã
|
||
[long mode]: https://en.wikipedia.org/wiki/Long_mode
|
||
[memory segmentation]: https://en.wikipedia.org/wiki/X86_memory_segmentation
|
||
|
||
ããŒãããŒããŒãæžãã®ã«ã¯ã¢ã»ã³ããªèšèªãå¿
èŠãšããããããäœãèããã«ããã»ããµãŒã®ãã®ã¬ãžã¹ã¿ã«ãã®å€ãæžã蟌ãã§ãã ãããã®ãããªå匷ã®åœ¹ã«ç«ããªãäœæ¥ãããããããã®ã§ãã¡ãã£ãšé¢åãããã§ããã§ãã®ã§ãã®èšäºã§ã¯ããŒãããŒããŒã®å¶äœã«ã€ããŠã¯é£ã°ããŠã代ããã«[bootimage]ãšãããèªåã§ã«ãŒãã«ã®åã«ããŒãããŒãã眮ããŠãããããŒã«ã䜿ããŸãããã
|
||
|
||
[bootimage]: https://github.com/rust-osdev/bootimage
|
||
|
||
èªåã®ããŒãããŒããŒãäœãããšã«èå³ããã人ããæåŸ
äžãããããã«é¢ããèšäºãèšç»äžã§ãïŒ
|
||
|
||
#### MultibootæšæºèŠæ Œ
|
||
ãã¹ãŠã®ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ããèªèº«ã«ã®ã¿å¯Ÿå¿ããŠããããŒãããŒããŒãå®è£
ãããšããããšãé¿ããããã«ã1995幎ã«[ããªãŒãœãããŠã§ã¢è²¡å£][Free Software Foundation]ã[Multiboot]ãšããããŒãããŒããŒã®å
¬éæšæºèŠæ Œãçå®ããŠããŸãããã®æšæºèŠæ Œã§ã¯ãããŒãããŒããŒãšãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®ã€ã³ã¿ãŒãã§ãŒã¹ãå®çŸ©ãããŠãããMultibootã«æºæ ããããŒãããŒããŒã§ããã°ãåããããã«æºæ ãããã¹ãŠã®ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ãèªã¿èŸŒããããã«ãªã£ãŠããŸãããã®ãªãã¡ã¬ã³ã¹å®è£
ãšããŠãLinuxã·ã¹ãã ã§äžçªäººæ°ã®ããŒãããŒããŒã§ãã[GNU GRUB]ããããŸãã
|
||
|
||
[Free Software Foundation]: https://ja.wikipedia.org/wiki/ããªãŒãœãããŠã§ã¢è²¡å£
|
||
[Multiboot]: https://wiki.osdev.org/Multiboot
|
||
[GNU GRUB]: https://ja.wikipedia.org/wiki/GNU_GRUB
|
||
|
||
ã«ãŒãã«ãMultibootã«æºæ ãããã«ã¯ãã«ãŒãã«ãã¡ã€ã«ã®å
é ã«ãããã[Multiboot header]ãæ¿å
¥ããã ãã§æžã¿ãŸãããã®ãããã§ãOSãGRUBã§èµ·åããã®ã¯ãšãŠãç°¡åã§ããããããGRUBãšMultibootæšæºèŠæ Œã«ã¯ããã€ãåé¡ããããŸãïŒ
|
||
|
||
[Multiboot header]: https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#OS-image-format
|
||
|
||
- ãããã¯32bitãããã¯ãã¢ãŒããããµããŒãããŠããŸããããã®ããã64bitãã³ã°ã¢ãŒãã«å€æŽããããã®CPUã®èšå®ã¯äŸç¶è¡ãå¿
èŠããããŸãã
|
||
- ãããã¯ãã«ãŒãã«ã§ã¯ãªãããŒãããŒããŒãã·ã³ãã«ã«ãªãããã«èšèšãããŠããŸããäŸãã°ãã«ãŒãã«ã¯[éåžžãšã¯ç°ãªãããã©ã«ãããŒãžãµã€ãº][adjusted default page size]ã§ãªã³ã¯ãããå¿
èŠããããããããªããšGRUBã¯Multiboot headerãèŠã€ããããšãã§ããŸãããä»ã«ããã«ãŒãã«ã«æž¡ããã[<ruby>ããŒãæ
å ±<rp> (</rp><rt>boot information</rt><rp>) </rp></ruby>][boot information]ã¯ãã¯ãªãŒã³ãªæœè±¡åãäžããŠããããã¢ãŒããã¯ãã£äŸåã®æ§é ãå€ãå«ãã§ããŸãã
|
||
- GRUBãMultibootæšæºèŠæ Œãããã¥ã¡ã³ããå
å®ããŠããŸããã
|
||
- ã«ãŒãã«ãã¡ã€ã«ããããŒã¿ãã«ãã£ã¹ã¯ã€ã¡ãŒãžãäœãã«ã¯ããã¹ãã·ã¹ãã ã«GRUBãã€ã³ã¹ããŒã«ãããŠããå¿
èŠããããŸããããã«ãããMacãšWindowsäžã§ã®éçºã¯æ¯èŒçé£ãããªã£ãŠããŸãã
|
||
|
||
[adjusted default page size]: https://wiki.osdev.org/Multiboot#Multiboot_2
|
||
[boot information]: https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Boot-information-format
|
||
|
||
ãããã®æ¬ ç¹ãèæ
®ããç§éã¯GRUBãšMultibootæšæºèŠæ Œã䜿ããªãããšã«æ±ºããŸãããããããããªãã®ã«ãŒãã«ãGRUBã·ã¹ãã äžã§èªã¿èŸŒããããã«ãç§éã®[bootimage]ããŒã«ã«Multibootã®ãµããŒãã远å ããããšãèšç»ããŠããŸããMultibootæºæ ãªã«ãŒãã«ãæžãããå Žåã¯ããã®ããã°ã·ãªãŒãºã®[第1ç][first edition]ãã芧ãã ããã
|
||
|
||
[first edition]: @/edition-1/_index.md
|
||
|
||
### UEFI
|
||
|
||
ïŒä»ã®æUEFIã®ãµããŒãã¯æäŸããŠããŸãããããã²ãšãããããšæã£ãŠããŸãïŒãæäŒãããã ããå Žåã¯ã [GitHub issue](https://github.com/phil-opp/blog_os/issues/349)ã§æããŠãã ãããïŒ
|
||
|
||
## æå°ã®ã«ãŒãã«
|
||
ã©ã®ããã«ã³ã³ãã¥ãŒã¿ãèµ·åããã®ãã«ã€ããŠãã£ãããšçè§£ã§ããã®ã§ãèªåã§æå°ã®ã«ãŒãã«ãæžããŠã¿ãŸããããç®æšã¯ãèµ·åãããç»é¢ã«"Hello, World!"ãšåºåãããããªãã£ã¹ã¯ã€ã¡ãŒãžãäœãããšã§ãããšããããã§ãåã®èšäºã®[<ruby>ç¬ç«ãã<rp> (</rp><rt>freestanding</rt><rp>) </rp></ruby>Rustãã€ããª][freestanding Rust binary]ãããšã«ããŠäœã£ãŠãããŸãã
|
||
|
||
èŠããŠããŸããããã®ç¬ç«ãããã€ããªã¯`cargo`ã䜿ã£ãŠãã«ãããŸãããããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã«äŸã£ãŠç°ãªããšã³ããªãã€ã³ãåãšã³ã³ãã€ã«ãã©ã°ãå¿
èŠãªã®ã§ãããããã¯`cargo`ã¯æšæºã§ã¯ **ãã¹ãã·ã¹ãã **ïŒããªãã®äœ¿ã£ãŠããã·ã¹ãã ïŒåãã«ãã«ãããããã§ããäŸãã°Windowsäžã§èµ°ãã«ãŒãã«ãšããã®ã¯ããŸãæå³ããªããç§éã®æãåäœã§ã¯ãããŸããã代ããã«ãæç¢ºã«å®çŸ©ããã **ã¿ãŒã²ããã·ã¹ãã ** åãã«ã³ã³ãã€ã«ã§ãããšçæ³çã§ãã
|
||
|
||
### Rustã®Nightlyçãã€ã³ã¹ããŒã«ãã
|
||
Rustã«ã¯**stable**ã**beta**ã**nightly**ã®3ã€ã®ãªãªãŒã¹ãã£ã³ãã«ããããŸããRust Bookã¯ãããã®3ã€ã®ãã£ã³ãã«ã®éãããšãŠãè¯ã説æããŠããã®ã§ãäžåºŠ[確èªããŠã¿ãŠãã ãã](https://doc.rust-jp.rs/book-ja/appendix-07-nightly-rust.html)ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ããã«ãããã«ã¯ãnightlyãã£ã³ãã«ã§ããå©çšã§ããªãããã€ãã®å®éšçæ©èœã䜿ãå¿
èŠãããã®ã§ãRustã®nightlyçãã€ã³ã¹ããŒã«ããããšã«ãªããŸãã
|
||
|
||
Rustã®å®è¡ç°å¢ã管çããã®ã«ã¯ã[rustup]ã匷ãããããããŸããnightlyãbetaãstableçã®ã³ã³ãã€ã©ãããããã€ã³ã¹ããŒã«ããããšãã§ããŸãããã¢ããããŒãããã®ãç°¡åã§ããçŸåšã®ãã£ã¬ã¯ããªã«nightlyã³ã³ãã€ã©ã䜿ãããã«ããã«ã¯ã`rustup override set nightly`ãšå®è¡ããŠãã ããããããã¯ã`rust-toolchain`ãšãããã¡ã€ã«ã«`nightly`ãšèšå
¥ããŠãããžã§ã¯ãã®ã«ãŒããã£ã¬ã¯ããªã«çœ®ãããšã§ãæå®ã§ããŸããNightlyçã䜿ã£ãŠããããšã¯ã`rustc --version`ãšå®è¡ããããšã§ç¢ºãããããŸãã衚瀺ãããããŒãžã§ã³åã®æ«å°Ÿã«`-nightly`ãšããã¯ãã§ãã
|
||
|
||
[rustup]: https://www.rustup.rs/
|
||
|
||
nightlyã³ã³ãã€ã©ã§ã¯ããããã**feature flag**ããã¡ã€ã«ã®å
é ã«ã€ããããšã§ããããããªå®éšçæ©èœã䜿ãããšãéžæã§ããŸããäŸãã°ã`#![feature(asm)]`ã`main.rs`ã®å
é ã«ã€ããããšã§ãã€ã³ã©ã€ã³ã¢ã»ã³ããªã®ããã®å®éšçãª[`asm!`ãã¯ã][`asm!` macro]ãæå¹åããããšãã§ããŸãããã ãããããã®å®éšçæ©èœã¯å
šããã£ãŠ<ruby>äžå®å®<rp> (</rp><rt>unstable</rt><rp>) </rp></ruby>ã§ãããå°æ¥ã®RustããŒãžã§ã³ã«ãããŠã¯äºåã®èŠåãªã倿Žããããåãé€ããããããå¯èœæ§ãããããšã«æ³šæããŠãã ããããã®ããã絶察ã«å¿
èŠãªãšãã«ã®ã¿ãããã䜿ãããšã«ããŸãã
|
||
|
||
[`asm!` macro]: https://doc.rust-lang.org/unstable-book/library-features/asm.html
|
||
|
||
### ã¿ãŒã²ããã®ä»æ§
|
||
Cargoã¯`--target`ãã©ã¡ãŒã¿ã䜿ã£ãŠããŸããŸãªã¿ãŒã²ããããµããŒãããŸããã¿ãŒã²ããã¯ãããã[target <ruby>triple<rp> (</rp><rt>3ã€çµ</rt><rp>) </rp></ruby>][target triple]ã«ãã£ãŠè¡šãããŸããããã¯CPUã¢ãŒããã¯ãã£ã補é å
ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ããããŠ[ABI]ã衚ããŸããäŸãã°ã`x86_64-unknown-linux-gnu`ãšããtarget tripleã¯ã`x86_64`ã®CPUã補é å
äžæãGNU ABIã®Linuxãªãã¬ãŒãã£ã³ã°ã·ã¹ãã åãã®ã·ã¹ãã ã衚ããŸããRustã¯[å€ãã®target triple][platform-support]ããµããŒãããŠããããã®äžã«ã¯Androidã®ããã®`arm-linux-androideabi`ã[WebAssemblyã®ããã®`wasm32-unknown-unknown`](https://www.hellorust.com/setup/wasm-target/)ãªã©ããããŸãã
|
||
|
||
[target triple]: https://clang.llvm.org/docs/CrossCompilation.html#target-triple
|
||
[ABI]: https://stackoverflow.com/a/2456882
|
||
[platform-support]: https://forge.rust-lang.org/release/platform-support.html
|
||
[custom-targets]: https://doc.rust-lang.org/nightly/rustc/targets/custom.html
|
||
|
||
ããããªãããç§éã®ã¿ãŒã²ããã·ã¹ãã ã«ã¯ãããã€ãç¹æ®ãªèšå®ãã©ã¡ãŒã¿ãå¿
èŠã«ãªããŸãïŒäŸãã°ããã®äžã§ã¯OSãèµ°ã£ãŠããªãããªã©ïŒããªã®ã§ã[æ¢åã®target triple][platform-support]ã¯ã©ããåœãŠã¯ãŸããŸããããããããããšã«ãRustã§ã¯JSONãã¡ã€ã«ã䜿ã£ãŠ[ç¬èªã®ã¿ãŒã²ãã][custom-targets]ãå®çŸ©ã§ããŸããäŸãã°ã`x86_64-unknown-linux-gnu`ãšããã¿ãŒã²ããã衚ãJSONãã¡ã€ã«ã¯ãããªæãã§ãã
|
||
|
||
```json
|
||
{
|
||
"llvm-target": "x86_64-unknown-linux-gnu",
|
||
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
|
||
"arch": "x86_64",
|
||
"target-endian": "little",
|
||
"target-pointer-width": "64",
|
||
"target-c-int-width": "32",
|
||
"os": "linux",
|
||
"executables": true,
|
||
"linker-flavor": "gcc",
|
||
"pre-link-args": ["-m64"],
|
||
"morestack": false
|
||
}
|
||
```
|
||
|
||
ã»ãšãã©ã®ãã£ãŒã«ãã¯LLVMããã®ãã©ãããã©ãŒã åãã®ã³ãŒããçæããããã«å¿
èŠãªãã®ã§ããäŸãã°ã[`data-layout`]ãã£ãŒã«ãã¯çš®ã
ã®æŽæ°ãæµ®åå°æ°ç¹æ°ããã€ã³ã¿åã®å€§ãããå®çŸ©ããŠããŸããæ¬¡ã«ã`target-pointer-width`ã®ãããªãæ¡ä»¶ä»ãã³ã³ãã€ã«ã«çšãããããã£ãŒã«ãããããŸãã第3ã®çš®é¡ã®ãã£ãŒã«ãã¯ã¯ã¬ãŒããã©ã®ããã«ãã«ããããã¹ãããå®çŸ©ããŸããäŸãã°ã`pre-link-args`ãã£ãŒã«ãã¯[<ruby>ãªã³ã«<rp> (</rp><rt>linker</rt><rp>) </rp></ruby>][linker]ã«æž¡ãããåŒæ°ãæå®ããŠããŸãã
|
||
|
||
[`data-layout`]: https://llvm.org/docs/LangRef.html#data-layout
|
||
[linker]: https://ja.wikipedia.org/wiki/ãªã³ã±ãŒãžãšãã£ã¿
|
||
|
||
ç§éã®ã«ãŒãã«ã`x86_64`ã®ã·ã¹ãã ãã¿ãŒã²ãããšããã®ã§ãç§éã®ã¿ãŒã²ãã仿§ãäžã®ãã®ãšéåžžã«ãã䌌ããã®ã«ãªãã§ãããã`x86_64-blog_os.json`ãšãããã¡ã€ã«ïŒã奜ããªååãéžãã§ãã ããïŒãäœããå
±éããèŠçŽ ãåãããšããããå§ããŸãããã
|
||
|
||
```json
|
||
{
|
||
"llvm-target": "x86_64-unknown-none",
|
||
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
|
||
"arch": "x86_64",
|
||
"target-endian": "little",
|
||
"target-pointer-width": "64",
|
||
"target-c-int-width": "32",
|
||
"os": "none",
|
||
"executables": true
|
||
}
|
||
```
|
||
|
||
<ruby>ãã¢ã¡ã¿ã«<rp> (</rp><rt>bare metal</rt><rp>) </rp></ruby>ç°å¢ã§å®è¡ããã®ã§ã`llvm-target`ã®OSãå€ãã`os`ãã£ãŒã«ãã`none`ã«ããããšã«æ³šç®ããŠãã ããã
|
||
|
||
以äžã®ããã«ãã«é¢ä¿ããé
ç®ã远å ããŸãã
|
||
|
||
```json
|
||
"linker-flavor": "ld.lld",
|
||
"linker": "rust-lld",
|
||
```
|
||
|
||
ç§éã®ã«ãŒãã«ããªã³ã¯ããã®ã«ããã©ãããã©ãŒã æšæºã®ïŒLinuxã¿ãŒã²ããããµããŒãããŠããªããããããªãïŒãªã³ã«ã§ã¯ãªããRustã«ä»å±ããŠããã¯ãã¹ãã©ãããã©ãŒã ã®[LLD]ãªã³ã«ã䜿çšããŸãã
|
||
|
||
[LLD]: https://lld.llvm.org/
|
||
|
||
```json
|
||
"panic-strategy": "abort",
|
||
```
|
||
|
||
ãã®èšå®ã¯ãã¿ãŒã²ããããããã¯æã®[stack unwinding]ããµããŒãããŠããªãã®ã§ãããã°ã©ã ã¯ä»£ããã«çŽæ¥<ruby>äžæ<rp> (</rp><rt>abort</rt><rp>) </rp></ruby>ããªããã°ãªããªããšããããšãæå®ããŠããŸããããã¯ãCargo.tomlã«`panic = "abort"`ãšããèšå®ãæžãã®ã«çããã§ããããåŸè
ã®èšå®ãæ¶ããŠãæ§ããŸããïŒãã®ã¿ãŒã²ããèšå®ã¯ãCargo.tomlã®èšå®ãšç°ãªãããã®ããšè¡ã`core`ã©ã€ãã©ãªã®åã³ã³ãã€ã«ã«ãé©çšãããŸããã§ãã®ã§ãCargo.tomlã«èšå®ããæ¹ã奜ã¿ã ã£ããšããŠãããã®èšå®ã远å ããããã«ããŠãã ããïŒã
|
||
|
||
[stack unwinding]: https://www.bogotobogo.com/cplusplus/stackunwinding.php
|
||
|
||
```json
|
||
"disable-redzone": true,
|
||
```
|
||
|
||
ã«ãŒãã«ãæžããŠãã以äžãããæç¹ã§<ruby>å²ã蟌ã¿<rp> (</rp><rt>interrupt</rt><rp>) </rp></ruby>ãåŠçããªããã°ãªããªããªãã§ãããããããå®å
šã«è¡ãããã«ã **"red zone"** ãšåŒã°ãããããçš®ã®ã¹ã¿ãã¯ãã€ã³ã¿æé©åãç¡å¹åããå¿
èŠããããŸããããããªããšãã¹ã¿ãã¯ã®<ruby>ç Žæ<rp> (</rp><rt>corruption</rt><rp>) </rp></ruby>ãåŒãèµ·ãããŠããŸãæããããããã§ãããã詳ããã¯ã[red zoneã®ç¡å¹å][disabling the red zone]ãšããå¥èšäºãã芧ãã ããã
|
||
|
||
[disabling the red zone]: @/edition-2/posts/02-minimal-rust-kernel/disable-red-zone/index.md
|
||
|
||
```json
|
||
"features": "-mmx,-sse,+soft-float",
|
||
```
|
||
|
||
`features`ãã£ãŒã«ãã¯ãã¿ãŒã²ããã®<ruby>æ©èœ<rp> (</rp><rt>features</rt><rp>) </rp></ruby>ãæå¹å/ç¡å¹åããŸãããã€ãã¹ãåã«ã€ããããšã§`mmx`ãš`sse`ãšããæ©èœãç¡å¹åãããã©ã¹ãåã«ã€ããããšã§`soft-float`ãšããæ©èœãæå¹åããŠããŸããããããã®ãã©ã°ã®éã«ã¹ããŒã¹ã¯å
¥ããŠã¯ãªããããããããããšLLVMãæ©èœæååã®è§£éã«å€±æããŠããŸãããšã«æ³šæããŠãã ããã
|
||
|
||
`mmx`ãš`sse`ãšããæ©èœã¯ã[Single Instruction Multiple Data (SIMD)]åœä»€ããµããŒãããããæ±ºå®ããŸãããã®åœä»€ã¯ããã°ãã°ããã°ã©ã ãèããéãããŠãããŸãããããã倧ããªSIMDã¬ãžã¹ã¿ãOSã«ãŒãã«ã§äœ¿ãããšã¯æ§èœäžã®åé¡ã«ç¹ãããŸãã ãã®çç±ã¯ãã«ãŒãã«ã¯ãå²ã蟌ãŸããããã°ã©ã ãåéããåã«ããã¹ãŠã®ã¬ãžã¹ã¿ãå
ã«æ»ããªããšãããªãããã§ããããã¯ãã«ãŒãã«ãSIMDã®ç¶æ
ã®ãã¹ãŠããã·ã¹ãã ã³ãŒã«ãããŒããŠã§ã¢å²ã蟌ã¿ããããã³ã«ã¡ã€ã³ã¡ã¢ãªã«ä¿åããªããšãããªããšããããšãæå³ããŸããSIMDã®ç¶æ
æ
å ±ã¯ãšãŠã巚倧ïŒ512ã1600 bytesïŒã§ãå²ã蟌ã¿ã¯éåžžã«é »ç¹ã«èµ·ãããããããªãã®ã§ãä¿åã»åŸ©å
ã®æäœããã®ããã«è¿œå ãããã®ã¯æ§èœã«ããªãã®æªåœ±é¿ãåãŒããŸãããããé¿ããããã«ãïŒã«ãŒãã«ã®äžã§èµ°ã£ãŠããã¢ããªã±ãŒã·ã§ã³ã§ã¯ãªãïŒïŒã«ãŒãã«äžã§SIMDãç¡å¹åããã®ã§ãã
|
||
|
||
[Single Instruction Multiple Data (SIMD)]: https://ja.wikipedia.org/wiki/SIMD
|
||
|
||
SIMDãç¡å¹åããããšã«ããåé¡ã«ã`x86_64`ã«ãããæµ®åå°æ°ç¹æŒç®ã¯æšæºã§ã¯SIMDã¬ãžã¹ã¿ãå¿
èŠãšãããšããããšããããŸãããã®åé¡ã解決ããããã`soft-float`æ©èœã远å ããŸããããã¯ããã¹ãŠã®æµ®åå°æ°ç¹æŒç®ãéåžžã®æŽæ°ã«åºã¥ãããœãããŠã§ã¢äžã®é¢æ°ã䜿ã£ãŠãšãã¥ã¬ãŒããããšãããã®ã§ãã
|
||
|
||
ãã詳ããã¯ã[SIMDãç¡å¹åãã](@/edition-2/posts/02-minimal-rust-kernel/disable-simd/index.md)ããšã«é¢ããç§éã®èšäºãèªãã§ãã ããã
|
||
|
||
#### ãŸãšãããš
|
||
ç§éã®ã¿ãŒã²ãã仿§ãã¡ã€ã«ã¯ä»ãã®ããã«ãªã£ãŠããã¯ãã§ãã
|
||
|
||
```json
|
||
{
|
||
"llvm-target": "x86_64-unknown-none",
|
||
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
|
||
"arch": "x86_64",
|
||
"target-endian": "little",
|
||
"target-pointer-width": "64",
|
||
"target-c-int-width": "32",
|
||
"os": "none",
|
||
"executables": true,
|
||
"linker-flavor": "ld.lld",
|
||
"linker": "rust-lld",
|
||
"panic-strategy": "abort",
|
||
"disable-redzone": true,
|
||
"features": "-mmx,-sse,+soft-float"
|
||
}
|
||
```
|
||
|
||
### ã«ãŒãã«ããã«ããã
|
||
ç§éã®æ°ããã¿ãŒã²ããã®ã³ã³ãã€ã«ã«ã¯Linuxã®æ
£ç¿ã«å£ããŸãïŒçç±ã¯ç¥ããŸãããLLVMã®ããã©ã«ãã§ãããšããã ãã§ã¯ãªãã§ããããïŒãã€ãŸãã[åã®èšäº][previous post]ã§èª¬æããããã«`_start`ãšããååã®ãšã³ããªãã€ã³ããèŠããšããããšã§ãã
|
||
|
||
[previous post]: @/edition-2/posts/01-freestanding-rust-binary/index.ja.md
|
||
|
||
```rust
|
||
// src/main.rs
|
||
|
||
#![no_std] // don't link the Rust standard library
|
||
#![no_main] // disable all Rust-level entry points
|
||
|
||
use core::panic::PanicInfo;
|
||
|
||
/// This function is called on panic.
|
||
#[panic_handler]
|
||
fn panic(_info: &PanicInfo) -> ! {
|
||
loop {}
|
||
}
|
||
|
||
#[no_mangle] // don't mangle the name of this function
|
||
pub extern "C" fn _start() -> ! {
|
||
// this function is the entry point, since the linker looks for a function
|
||
// named `_start` by default
|
||
loop {}
|
||
}
|
||
```
|
||
|
||
ãã¹ãOSãäœã§ãããã«ãããããããšã³ããªãã€ã³ãã¯`_start`ãšããååã§ãªããã°ãªããªãããšã«æ³šæããŠãã ããã
|
||
|
||
ããã§ãç§éã®æ°ããã¿ãŒã²ããã®ããã®ã«ãŒãã«ããJSONãã¡ã€ã«åã`--target`ãšããŠæž¡ãããšã§ãã«ãã§ããããã«ãªããŸããã
|
||
|
||
```
|
||
> cargo build --target x86_64-blog_os.json
|
||
|
||
error[E0463]: can't find crate for `core`
|
||
```
|
||
|
||
倱æããŸãããïŒãšã©ãŒã¯Rustã³ã³ãã€ã©ã[`core`ã©ã€ãã©ãª][`core` library]ãèŠã€ããããªããªã£ããšèšã£ãŠããŸãããã®ã©ã€ãã©ãªã¯ã`Result` ã `Option`ãã€ãã¬ãŒã¿ã®ãããªåºæ¬çãªRustã®åãæã£ãŠãããæé»ã®ãã¡ã«ãã¹ãŠã®`no_std`ãªã¯ã¬ãŒãã«ãªã³ã¯ãããŠããŸãã
|
||
|
||
[`core` library]: https://doc.rust-lang.org/nightly/core/index.html
|
||
|
||
åé¡ã¯ãcoreã©ã€ãã©ãªã¯Rustã³ã³ãã€ã©ãšäžç·ã«<ruby>ã³ã³ãã€ã«æžã¿<rp> (</rp><rt>precompiled</rt><rp>) </rp></ruby>ã©ã€ãã©ãªãšããŠé
åžãããŠãããšããããšã§ãããã®ãããããã¯ãç§éç¬èªã®ã¿ãŒã²ããã§ã¯ãªãããµããŒããããŠããhost tripleïŒäŸãã° `x86_64-unknown-linux-gnu`ïŒã§ã®ã¿äœ¿ããã®ã§ããä»ã®ã¿ãŒã²ããã®ããã«ã³ãŒããã³ã³ãã€ã«ããããšãã«ã¯ã`core`ããããã®ã¿ãŒã²ããã«åããŠåã³ã³ãã€ã«ããå¿
èŠããããŸãã
|
||
|
||
#### `build-std`ãªãã·ã§ã³
|
||
|
||
ããã§cargoã®[`build-std`æ©èœ][`build-std` feature]ã®åºçªã§ããããã䜿ããš`core`ããã®ä»ã®æšæºã©ã€ãã©ãªã¯ã¬ãŒãã«ã€ããŠãRustã€ã³ã¹ããŒã«æã«äžç·ã«ã€ããŠããã³ã³ãã€ã«æžã¿ããŒãžã§ã³ã䜿ã代ããã«ãå¿
èŠã«å¿ããŠåã³ã³ãã€ã«ããããšãã§ããŸããããã¯ãšãŠãæ°ãããŸã 宿ããŠããªãã®ã§ã<ruby>äžå®å®<rp> (</rp><rt>unstable</rt><rp>) </rp></ruby>æ©èœãšãããŠããã[nightly Rustã³ã³ãã€ã©][nightly Rust compilers]ã§ã®ã¿å©çšå¯èœã§ãã
|
||
|
||
[`build-std` feature]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std
|
||
[nightly Rust compilers]: #installing-rust-nightly
|
||
|
||
ãã®æ©èœã䜿ãããã«ã¯ã[cargoã®èšå®][cargo configuration]ãã¡ã€ã«ã`.cargo/config.toml`ã«äœããæ¬¡ã®å
å®¹ãæžããŸãããã
|
||
|
||
```toml
|
||
# in .cargo/config.toml
|
||
|
||
[unstable]
|
||
build-std = ["core", "compiler_builtins"]
|
||
```
|
||
|
||
ããã¯cargoã«`core`ãš`compiler_builtins`ã©ã€ãã©ãªãåã³ã³ãã€ã«ããããåœä»€ããŸããåŸè
ãå¿
èŠãªã®ã¯`core`ãããã«äŸåããŠããããã§ãã ãããã®ã©ã€ãã©ãªãåã³ã³ãã€ã«ããããã«ã¯ãcargoãRustã®ãœãŒã¹ã³ãŒãã«ã¢ã¯ã»ã¹ã§ããå¿
èŠããããŸããããã¯`rustup component add rust-src`ã§ã€ã³ã¹ããŒã«ã§ããŸãã
|
||
|
||
<div class="note">
|
||
|
||
**泚æ:** `unstable.build-std`èšå®ããŒã䜿ãã«ã¯ãå°ãªããšã2020-07-15以éã®Rust nightlyãå¿
èŠã§ãã
|
||
|
||
</div>
|
||
|
||
`unstable.build-std`èšå®ããŒãã»ãããã`rust-src`ã³ã³ããŒãã³ããã€ã³ã¹ããŒã«ãããããã«ãã³ãã³ããããäžåºŠå®è¡ããŸãããã
|
||
|
||
```
|
||
> cargo build --target x86_64-blog_os.json
|
||
Compiling core v0.0.0 (/âŠ/rust/src/libcore)
|
||
Compiling rustc-std-workspace-core v1.99.0 (/âŠ/rust/src/tools/rustc-std-workspace-core)
|
||
Compiling compiler_builtins v0.1.32
|
||
Compiling blog_os v0.1.0 (/âŠ/blog_os)
|
||
Finished dev [unoptimized + debuginfo] target(s) in 0.29 secs
|
||
```
|
||
|
||
ä»åã¯ã`cargo build`ã`core`ã`rustc-std-workspace-core` (`compiler_builtins`ã®äŸåã§ã)ããã㊠`compiler_builtins`ãç§éã®ã«ã¹ã¿ã ã¿ãŒã²ããåãã«åã³ã³ãã€ã«ããŠãããšããããšãããããŸãã
|
||
|
||
#### ã¡ã¢ãªé¢ä¿ã®<ruby>çµã¿èŸŒã¿é¢æ°<rp> (</rp><rt>intrinsics</rt><rp>) </rp></ruby>
|
||
|
||
Rustã³ã³ãã€ã©ã¯ããã¹ãŠã®ã·ã¹ãã ã«ãããŠãç¹å®ã®çµã¿èŸŒã¿é¢æ°ãå©çšå¯èœã§ãããšããããšãåæã«ããŠããŸãããããã®é¢æ°ã®å€ãã¯ãç§éãã¡ããã©åã³ã³ãã€ã«ãã`compiler_builtins`ã¯ã¬ãŒãã«ãã£ãŠæäŸãããŠããŸããããããªãããéåžžã·ã¹ãã ã®Cã©ã€ãã©ãªã«ãã£ãŠæäŸãããŠããã®ã§æšæºã§ã¯æå¹åãããŠããªããã¡ã¢ãªé¢ä¿ã®é¢æ°ãããã€ããããŸãããããã®é¢æ°ã«ã¯ãã¡ã¢ãªãããã¯å
ã®ãã¹ãŠã®ãã€ããäžããããå€ã«ã»ãããã`memset`ãã¡ã¢ãªãŒãããã¯ãä»ã®ãããã¯ãžãšã³ããŒãã`memcpy`ã2ã€ã®ã¡ã¢ãªãŒãããã¯ãæ¯èŒãã`memcmp`ãªã©ããããŸãããããã®é¢æ°ã¯ã©ãããçŸåšã®æ®µéã§æã
ã®ã«ãŒãã«ãã³ã³ãã€ã«ããã®ã«å¿
èŠãšããããã§ã¯ãããŸããããã³ãŒãã远å ããŠãããšããã«å¿
èŠã«ãªãã§ãããïŒããšãã°ãæ§é äœãã³ããŒããããªã©ïŒã
|
||
|
||
ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®Cã©ã€ãã©ãªã«ãªã³ã¯ããããšã¯ã§ããŸããã®ã§ããããã®é¢æ°ãã³ã³ãã€ã©ã«äžããŠããå¥ã®æ¹æ³ãå¿
èŠã«ãªããŸãããã®ããã®æ¹æ³ãšããŠèãããããã®ã®äžã€ããèªåã§`memset`ãå®è£
ããïŒã³ã³ãã€ã«äžã®èªåãªããŒã ãé²ãããïŒ`#[no_mangle]`ã¢ããªãã¥ãŒãããããã«é©çšããããšã§ãããããããããããããšããããã®é¢æ°ã®å®è£
ã®ã¡ãã£ãšãããã¹ãæªå®çŸ©åäœã«ç¹ããããããå±éºã§ããããšãã°ã`for`ã«ãŒãã䜿ã£ãŠ`memcpy`ãå®è£
ãããšç¡éååž°ãèµ·ãããŠããŸããããããŸããããªããªãã`for`ã«ãŒãã¯æé»ã®ãã¡ã«[`IntoIterator::into_iter`]ãã¬ã€ãã¡ãœãããåŒã³åºããŠãããããã`memcpy`ãåã³åŒã³åºããŠãããããããªãããã§ãããªã®ã§ã代ããã«æ¢åã®ãããã¹ããããå®è£
ãåå©çšããã®ãè¯ãã§ãããã
|
||
|
||
[`IntoIterator::into_iter`]: https://doc.rust-lang.org/stable/core/iter/trait.IntoIterator.html#tymethod.into_iter
|
||
|
||
ãããããããšã«ã`compiler_builtins`ã¯ã¬ãŒãã«ã¯ãããã®å¿
èŠãªé¢æ°ãã¹ãŠã®å®è£
ãå«ãŸããŠãããæšæºã§ã¯Cã©ã€ãã©ãªã®å®è£
ãšç«¶åããªãããã«ç¡å¹åãããŠããã ããªã®ã§ããããã¯cargoã®[`build-std-features`]ãã©ã°ã`["compiler-builtins-mem"]`ã«èšå®ããããšã§æå¹åã§ããŸãã`build-std`ãã©ã°ãšåãããã«ããã®ãã©ã°ã¯ã³ãã³ãã©ã€ã³ã§`-Z`ãã©ã°ãšããŠæž¡ãããšãã§ããã°ã`.cargo/config.toml`ãã¡ã€ã«ã®`unstable`ããŒãã«ã§èšå®ããããšãã§ããŸãããã«ãæã¯åžžã«ãã®ãã©ã°ãã»ãããããã®ã§ãèšå®ãã¡ã€ã«ãäœ¿ãæ¹ãè¯ãã§ãããïŒ
|
||
|
||
[`build-std-features`]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std-features
|
||
|
||
```toml
|
||
# in .cargo/config.toml
|
||
|
||
[unstable]
|
||
build-std-features = ["compiler-builtins-mem"]
|
||
```
|
||
|
||
ïŒ`compiler-builtins-mem`æ©èœã®ãµããŒãã远å ãããã®ã¯[ã€ãæè¿](https://github.com/rust-lang/rust/pull/77284)ãªã®ã§ã`2019-09-30`以éã®Rust nightlyãå¿
èŠã§ããïŒ
|
||
|
||
ãã®ãšããè£ã§`compiler_builtins`ã¯ã¬ãŒãã®[`mem`æ©èœ][`mem` feature]ãæå¹åãããŠããŸããããã«ããããã®ã¯ã¬ãŒãã®[`memcpy`ãªã©ã®å®è£
][`memcpy` etc. implementations]ã«`#[no_mangle]`ã¢ããªãã¥ãŒããé©çšããããªã³ã«ãããããå©çšã§ããããã«ãªã£ãŠããŸãããããã®é¢æ°ã¯ä»ã®ãšãã[æé©åãããŠããã][not optimized]ãæ§èœã¯æé«ã§ã¯ãªããããããªããã®ã®ãå°ãªããšãæ£ããå®è£
ã§ã¯ãããšããããšã¯ç¥ã£ãŠãã䟡å€ãããã§ãããã`x86_64`ã«ã€ããŠã¯ã[ãããã®é¢æ°ãç¹æ®ãªã¢ã»ã³ããªåœä»€ã䜿ã£ãŠæé©åãã][memcpy rep movsb]ãã«ãªã¯ãšã¹ããæåºãããŠããŸãã
|
||
|
||
[`mem` feature]: https://github.com/rust-lang/compiler-builtins/blob/eff506cd49b637f1ab5931625a33cef7e91fbbf6/Cargo.toml#L51-L52
|
||
[`memcpy` etc. implementations]: (https://github.com/rust-lang/compiler-builtins/blob/eff506cd49b637f1ab5931625a33cef7e91fbbf6/src/mem.rs#L12-L69)
|
||
[not optimized]: https://github.com/rust-lang/compiler-builtins/issues/339
|
||
[memcpy rep movsb]: https://github.com/rust-lang/compiler-builtins/pull/365
|
||
|
||
ãã®å€æŽããã£ãŠãç§éã®ã«ãŒãã«ã¯ã³ã³ãã€ã©ã«å¿
èŠãšãããŠãããã¹ãŠã®é¢æ°ã®æå¹ãªå®è£
ãæã«å
¥ããã®ã§ãã³ãŒãããã£ãšè€éã«ãªã£ãŠãå€ãããã³ã³ãã€ã«ã§ããã§ãããã
|
||
|
||
#### æšæºã®ã¿ãŒã²ãããã»ãããã
|
||
|
||
`cargo build`ãåŒã³åºããã³ã«`--target`ãã©ã¡ãŒã¿ãæž¡ãã®ãé¿ããããã«ãããã©ã«ãã®ã¿ãŒã²ãããæžãæããããšãã§ããŸãããããããã«ã¯ã以äžã`.cargo/config.toml`ã®[cargoèšå®][cargo configuration]ãã¡ã€ã«ã«ä»ãå ããŸã:
|
||
|
||
[cargo configuration]: https://doc.rust-lang.org/cargo/reference/config.html
|
||
|
||
```toml
|
||
# in .cargo/config.toml
|
||
|
||
[build]
|
||
target = "x86_64-blog_os.json"
|
||
```
|
||
|
||
ããã¯ãæç€ºçã«`--target`åŒæ°ãæž¡ãããŠããªããšãã¯ã`x86_64-blog_os.json`ã¿ãŒã²ããã䜿ãããã«`cargo`ã«åœä»€ããŸããã€ãŸããç§éã¯ã«ãŒãã«ãã·ã³ãã«ãª`cargo build`ã³ãã³ãã§ãã«ãã§ãããšããããšã§ããcargoã®èšå®ã®ãªãã·ã§ã³ã«ã€ããŠãã詳ããç¥ãã«ã¯ã[å
¬åŒã®ããã¥ã¡ã³ã][cargo configuration]ãèªãã§ãã ããã
|
||
|
||
ããã«ãããã·ã³ãã«ãª`cargo build`ã³ãã³ãã§ããã¢ã¡ã¿ã«ã®ã¿ãŒã²ããã«ç§éã®ã«ãŒãã«ããã«ãã§ããããã«ãªããŸãããããããããŒãããŒããŒã«ãã£ãŠåŒã³åºãããç§éã®`_start`ãšã³ããªãã€ã³ãã¯ãŸã 空ã£ãœã§ããããããããããäœããç»é¢ã«åºåããŠã¿ãŸãããã
|
||
|
||
### ç»é¢ã«åºåãã
|
||
çŸåšã®æ®µéã§ç»é¢ã«æåãåºåããæãç°¡åãªæ¹æ³ã¯[VGAããã¹ããããã¡][VGA text buffer]ã§ããããã¯ç»é¢ã«åºåãããŠããå
容ãä¿æããŠããVGAããŒããŠã§ã¢ã«ããããããç¹æ®ãªã¡ã¢ãªã§ããéåžžãããã¯25è¡ãããªããããããã®è¡ã¯80æåã»ã«ãããªããŸããããããã®æåã»ã«ã¯ãèæ¯è²ãšåæ¯è²ä»ãã®ASCIIæåã衚瀺ããŸããç»é¢åºåã¯ãã®ããã«èŠããã§ãããïŒ
|
||
|
||
[VGA text buffer]: https://en.wikipedia.org/wiki/VGA-compatible_text_mode
|
||
|
||

|
||
|
||
次ã®èšäºã§ã¯ãVGAãããã¡ã®æ£ç¢ºãªã¬ã€ã¢ãŠãã«ã€ããŠè°è«ãããã®ããã®ã¡ãã£ãšãããã©ã€ããæžããŸãã"Hello World!"ãåºåããããã«ã¯ããããã¡ãã¢ãã¬ã¹`0xb8000`ã«ãããããããã®æåã»ã«ã¯ASCIIã®ãã€ããšè²ã®ãã€ããããªãããšãç¥ã£ãŠããå¿
èŠããããŸãã
|
||
|
||
å®è£
ã¯ãããªæãã«ãªããŸãïŒ
|
||
|
||
```rust
|
||
static HELLO: &[u8] = b"Hello World!";
|
||
|
||
#[no_mangle]
|
||
pub extern "C" fn _start() -> ! {
|
||
let vga_buffer = 0xb8000 as *mut u8;
|
||
|
||
for (i, &byte) in HELLO.iter().enumerate() {
|
||
unsafe {
|
||
*vga_buffer.offset(i as isize * 2) = byte;
|
||
*vga_buffer.offset(i as isize * 2 + 1) = 0xb;
|
||
}
|
||
}
|
||
|
||
loop {}
|
||
}
|
||
```
|
||
|
||
ãŸãã`0xb8000`ãšããæŽæ°ã[çãã€ã³ã¿][raw pointer]ã«ãã£ã¹ãããŸããæ¬¡ã«[<ruby>éç<rp> (</rp><rt>static</rt><rp>) </rp></ruby>][static]ãª`HELLO`ãšãã[ãã€ãå][byte string]倿°ã®èŠçŽ ã«å¯Ÿã[ã€ãã¬ãŒã][iterate]ããŸãã[`enumerate`]ã¡ãœããã䜿ãããšã§ã`for` ã«ãŒãã®å®è¡åæ°ã衚ã倿° `i` ãååŸããŸããã«ãŒãã®å
éšã§ã¯ã[`offset`]ã¡ãœããã䜿ã£ãŠæååã®ãã€ããšå¯Ÿå¿ããè²ã®ãã€ãïŒ`0xb`ã¯æããã·ã¢ã³è²ïŒãæžã蟌ãã§ããŸãã
|
||
|
||
[iterate]: https://doc.rust-jp.rs/book-ja/ch13-02-iterators.html
|
||
[static]: https://doc.rust-jp.rs/book-ja/ch10-03-lifetime-syntax.html#éçã©ã€ãã¿ã€ã
|
||
[`enumerate`]: https://doc.rust-lang.org/core/iter/trait.Iterator.html#method.enumerate
|
||
[byte string]: https://doc.rust-lang.org/reference/tokens.html#byte-string-literals
|
||
[raw pointer]: https://doc.rust-jp.rs/book-ja/ch19-01-unsafe-rust.html#çãã€ã³ã¿ãåç
§å€ããã
|
||
[`offset`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.offset
|
||
|
||
ãã¹ãŠã®ã¡ã¢ãªãžã®æžã蟌ã¿åŠçã®ã³ãŒããã[<ruby>`unsafe`<rp> (</rp><rt>å®å
šã§ãªã</rt><rp>) </rp></ruby>][`unsafe`]ãããã¯ãå²ãã§ããããšã«æ³šæããŠãã ããããã®çç±ã¯ãç§éã®äœã£ãçãã€ã³ã¿ãæ£ãããã®ã§ããããšãRustã³ã³ãã€ã©ã蚌æã§ããªãããã§ããçãã€ã³ã¿ã¯ã©ããªå Žæã§ãæãããã®ã§ãããŒã¿ã®ç Žæã«ã€ãªãããããããŸããããããã®æäœã`unsafe`ãããã¯ã«å
¥ããããšã§ãç§éã¯ãããæ£ããããšã確信ããŠãããšã³ã³ãã€ã©ã«äŒããŠããã®ã§ãããã ãã`unsafe`ãããã¯ã¯Rustã®å®å
šæ§ãã§ãã¯ãæ¶ãããã§ã¯ãªãã[远å ã§5ã€ã®ããšãã§ããããã«ãªã][five additional things]ã ããšããããšã«æ³šæããŠãã ããã
|
||
|
||
<div class="note">
|
||
|
||
**蚳泚:** 翻蚳æç¹(2020-10-20)ã§ã¯ããªã³ã¯å
ã®The Rust bookæ¥æ¬èªçã«ã¯ã远å ã§ã§ããããã«ãªãããšãã¯4ã€ããæžãããŠããŸããã
|
||
|
||
</div>
|
||
|
||
[`unsafe`]: https://doc.rust-jp.rs/book-ja/ch19-01-unsafe-rust.html
|
||
[five additional things]: https://doc.rust-jp.rs/book-ja/ch19-01-unsafe-rust.html#unsafeã®åŒ·å€§ãªåsuperpower
|
||
|
||
匷調ããŠããããã®ã§ããã **ãã®ãããªæ©èœã¯Rustã§ããã°ã©ãã³ã°ãããšãã«äœ¿ããããã®ã§ã¯ãããŸããïŒ** unsafeãããã¯å
ã§çãã€ã³ã¿ãæ±ããšéåžžã«ãããããããã§ããããšãã°ã泚æäžè¶³ã§ãããã¡ã®çµç«¯ã®ããã«å¥¥ã«æžã蟌ã¿ãè¡ã£ãŠããŸã£ãããããããããŸããã
|
||
|
||
ã§ãã®ã§ã`unsafe`ã®äœ¿çšã¯æå°éã«ãããã§ãããããããããã«ãRustã§ã¯å®å
šãª<ruby>abstraction<rp> (</rp><rt>æœè±¡åããããã®</rt><rp>) </rp></ruby>ãäœãããšãã§ããŸããããšãã°ãVGAãããã¡åãäœãããã®äžã«ãã¹ãŠã®unsafeãªæäœãã«ãã»ã«åããå€åŽããã®èª€ã£ãæäœã**äžå¯èœ**ã§ããããšãä¿èšŒã§ããã§ããããããããã°ã`unsafe`ã®éãæå°éã«ã§ãã[ã¡ã¢ãªå®å
šæ§][memory safety]ã䟵ããŠããªãããšã確ãã«ã§ããŸãããã®ãããªå®å
šãªVGAãããã¡ã® abstraction ãæ¬¡ã®èšäºã§äœããŸãã
|
||
|
||
[memory safety]: https://ja.wikipedia.org/wiki/ã¡ã¢ãªå®å
šæ§
|
||
|
||
## ã«ãŒãã«ãå®è¡ãã
|
||
|
||
ã§ã¯ãç®ã§èŠãŠåããåŠçãè¡ãå®è¡å¯èœãã¡ã€ã«ãæã«å
¥ããã®ã§ãå®è¡ããŠã¿ãŸãããããŸããã³ã³ãã€ã«ããç§éã®ã«ãŒãã«ããããŒãããŒããŒãšãªã³ã¯ããããšã«ãã£ãŠããŒã¿ãã«ãã£ã¹ã¯ã€ã¡ãŒãžã«ããå¿
èŠããããŸãããããŠããã®ãã£ã¹ã¯ã€ã¡ãŒãžãã[QEMU]ããŒãã£ã«ãã·ã³å
ããUSBã¡ã¢ãªã䜿ã£ãŠå®éã®ããŒããŠã§ã¢äžã§å®è¡ã§ããŸãã
|
||
|
||
### ããŒãã€ã¡ãŒãžãäœã
|
||
|
||
ã³ã³ãã€ã«ãããç§éã®ã«ãŒãã«ãããŒã¿ãã«ãã£ã¹ã¯ã€ã¡ãŒãžã«å€ããã«ã¯ãããŒãããŒããŒãšãªã³ã¯ããå¿
èŠããããŸãã[èµ·åã®ããã»ã¹ã®ã»ã¯ã·ã§ã³][section about booting]ã§åŠãã ããã«ãããŒãããŒããŒã¯CPUãåæåãã«ãŒãã«ãããŒããã圹å²ããããŸãã
|
||
|
||
[section about booting]: #the-boot-process
|
||
|
||
èªåã®ããŒãããŒããŒãæžããšãããã ãã§1ã€ã®ãããžã§ã¯ãã«ãªã£ãŠããŸãã®ã§ã代ããã«[`bootloader`]ã¯ã¬ãŒãã䜿ããŸãããããã®ã¯ã¬ãŒãã¯ãCã«äŸåãããRustãšã€ã³ã©ã€ã³ã¢ã»ã³ããªã ãã§åºæ¬çãªBIOSããŒãããŒããŒãå®è£
ããŠããŸããç§éã®ã«ãŒãã«ãèµ·åããããã«ãããäŸåé¢ä¿ã«è¿œå ããå¿
èŠããããŸãïŒ
|
||
|
||
[`bootloader`]: https://crates.io/crates/bootloader
|
||
|
||
```toml
|
||
# in Cargo.toml
|
||
|
||
[dependencies]
|
||
bootloader = "0.9.8"
|
||
```
|
||
|
||
bootloaderãäŸåãšããŠå ããããšã ãã§ããŒã¿ãã«ãã£ã¹ã¯ã€ã¡ãŒãžãå®éã«äœããããã§ã¯ãªããç§éã®ã«ãŒãã«ãã³ã³ãã€ã«åŸã«ããŒãããŒããŒã«ãªã³ã¯ããå¿
èŠããããŸããåé¡ã¯ãcargoã[<ruby>ãã«ãåŸ<rp> (</rp><rt>post-build</rt><rp>) </rp></ruby>ã«ã¹ã¯ãªãããèµ°ãããæ©èœ][post-build scripts]ãæã£ãŠããªãããšã§ãã
|
||
|
||
[post-build scripts]: https://github.com/rust-lang/cargo/issues/545
|
||
|
||
ãã®åé¡ã解決ãããããç§éã¯`bootimage`ãšããããŒã«ãäœããŸãããããã¯ããŸãã«ãŒãã«ãšããŒãããŒããŒãã³ã³ãã€ã«ãããããŠãããããªã³ã¯ããŠããŒã¿ãã«ãã£ã¹ã¯ã€ã¡ãŒãžãäœããŸãããã®ããŒã«ãã€ã³ã¹ããŒã«ããã«ã¯ã以äžã®ã³ãã³ããã¿ãŒããã«ã§å®è¡ããŠãã ããïŒ
|
||
|
||
```
|
||
cargo install bootimage
|
||
```
|
||
|
||
`bootimage`ãå®è¡ãããŒãããŒãããã«ãããã«ã¯ã`llvm-tools-preview`ãšããrustupã³ã³ããŒãã³ããã€ã³ã¹ããŒã«ããå¿
èŠããããŸããããã¯`rustup component add llvm-tools-preview`ãšå®è¡ããããšã§ã§ããŸãã
|
||
|
||
`bootimage`ãã€ã³ã¹ããŒã«ãã`llvm-tools-preview`ã远å ãããã以äžã®ããã«å®è¡ããããšã§ããŒã¿ãã«ãã£ã¹ã¯ã€ã¡ãŒãžãäœããŸãïŒ
|
||
|
||
```
|
||
> cargo bootimage
|
||
```
|
||
|
||
ãã®ããŒã«ãç§éã®ã«ãŒãã«ã`cargo build`ã䜿ã£ãŠåã³ã³ãã€ã«ããŠããããšãããããŸãããã®ãããããªãã®è¡ã£ã倿Žãèªåã§æ€ç¥ããŠãããŸãããã®åŸãbootloaderããã«ãããŸããããã«ã¯å°ãæéãããããããããŸãããä»ã®äŸåã¯ã¬ãŒããšåãããã«ããã«ãã¯äžåºŠããè¡ãããããã®éœåºŠãã£ãã·ã¥ãããã®ã§ã以éã®ãã«ãã¯ãã£ãšæ©ããªããŸããæçµçã«ã`bootimage`ã¯bootloaderãšããªãã®ã«ãŒãã«ãåäœãããããŒã¿ãã«ãã£ã¹ã¯ã€ã¡ãŒãžã«ããŸãã
|
||
|
||
ãã®ã³ãã³ããå®è¡ãããã`target/x86_64-blog_os/debug`ãã£ã¬ã¯ããªå
ã«`bootimage-blog_os.bin`ãšããååã®ããŒã¿ãã«ãã£ã¹ã¯ã€ã¡ãŒãžãããã¯ãã§ãããããããŒãã£ã«ãã·ã³å
ã§èµ·åããŠãããã§ãããå®éã®ããŒããŠã§ã¢äžã§èµ·åããããã«USBã¡ã¢ãªã«ã³ããŒããŠãããã§ãããïŒãã ããããã¯CDã€ã¡ãŒãžã§ã¯ãããŸãããCDã€ã¡ãŒãžã¯ç°ãªããã©ãŒããããæã€ã®ã§ããããCDã«çŒããŠãããŸããããŸããïŒã
|
||
|
||
#### ã©ãããä»çµã¿ãªã®ïŒ
|
||
`bootimage`ããŒã«ã¯ãè£ã§ä»¥äžã®ã¹ããããè¡ã£ãŠããŸãïŒ
|
||
|
||
- ç§éã®ã«ãŒãã«ã[ELF]ãã¡ã€ã«ã«ã³ã³ãã€ã«ããã
|
||
- äŸåã§ããbootloaderãã¹ã¿ã³ãã¢ãã³ã®å®è¡ãã¡ã€ã«ãšããŠã³ã³ãã€ã«ããã
|
||
- ã«ãŒãã«ã®ELFãã¡ã€ã«ã®ãã€ãåãããŒãããŒããŒã«ãªã³ã¯ããã
|
||
|
||
[ELF]: https://ja.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||
[rust-osdev/bootloader]: https://github.com/rust-osdev/bootloader
|
||
|
||
èµ·åæãããŒãããŒããŒã¯è¿œå ãããELFãã¡ã€ã«ãèªã¿ãè§£éããŸããæ¬¡ã«ããã°ã©ã éšã<ruby>ããŒãžããŒãã«<rp> (</rp><rt>page table</rt><rp>) </rp></ruby>ã®<ruby>ä»®æ³ã¢ãã¬ã¹<rp> (</rp><rt>virtual address</rt><rp>) </rp></ruby>ã«ããããã`.bss`éšããŒãã«ããã¹ã¿ãã¯ãã»ããã¢ããããŸããæåŸã«ããšã³ããªãã€ã³ãã®ã¢ãã¬ã¹ïŒç§éã®`_start`颿°ïŒãèªã¿ãããã«ãžã£ã³ãããŸãã
|
||
|
||
### QEMUã§èµ·åãã
|
||
|
||
ããã§ããã£ã¹ã¯ã€ã¡ãŒãžãä»®æ³ãã·ã³ã§èµ·åã§ããŸãã[QEMU]ã䜿ã£ãŠãããèµ·åããã«ã¯ã以äžã®ã³ãã³ããå®è¡ããŠãã ããïŒ
|
||
|
||
[QEMU]: https://www.qemu.org/
|
||
|
||
```
|
||
> qemu-system-x86_64 -drive format=raw,file=target/x86_64-blog_os/debug/bootimage-blog_os.bin
|
||
warning: TCG doesn't support requested feature: CPUID.01H:ECX.vmx [bit 5]
|
||
```
|
||
|
||
ããã«ããã以äžã®ãããªèŠãç®ã®å¥ã®ãŠã£ã³ããŠãéããŸãïŒ
|
||
|
||

|
||
|
||
ç§éã®æžãã"Hello World!"ãç»é¢ã«èŠããŸããã
|
||
|
||
### å®éã®ãã·ã³
|
||
|
||
USBã¡ã¢ãªã«ãããæžã蟌ãã§å®éã®ãã·ã³äžã§èµ·åããããšãå¯èœã§ãïŒ
|
||
|
||
```
|
||
> dd if=target/x86_64-blog_os/debug/bootimage-blog_os.bin of=/dev/sdX && sync
|
||
```
|
||
|
||
`sdX`ã¯ããªãã®USBã¡ã¢ãªã®ããã€ã¹åã§ãããã®ããã€ã¹äžã®ãã¹ãŠã®ããŒã¿ãäžæžããããŠããŸãã®ã§ã **æ£ããããã€ã¹åãéžãã§ããã®ããã確èªããŠãã ãã** ã
|
||
|
||
ã€ã¡ãŒãžãUSBã¡ã¢ãªã«æžã蟌ãã ããšã¯ãããããèµ·åããããšã«ãã£ãŠå®éã®ããŒããŠã§ã¢äžã§èµ°ãããããšãã§ããŸããç¹æ®ãªããŒãã¡ãã¥ãŒã䜿ã£ãããBIOSèšå®ã§èµ·åæã®åªå
é äœãå€ããUSBã¡ã¢ãªããèµ·åããããšãéžæããå¿
èŠãããã§ãããããã ãã`bootloader`ã¯ã¬ãŒãã¯UEFIããµããŒãããŠããªãã®ã§ãUEFIãã·ã³äžã§ã¯ããŸãåäœããªããšããããšã«æ³šæããŠãã ããã
|
||
|
||
### `cargo run`ã䜿ã
|
||
|
||
QEMUäžã§ããç°¡åã«ç§éã®ã«ãŒãã«ãèµ°ãããããã«ãcargoã®`runner`èšå®ã䜿ããŸãã
|
||
|
||
```toml
|
||
# in .cargo/config.toml
|
||
|
||
[target.'cfg(target_os = "none")']
|
||
runner = "bootimage runner"
|
||
```
|
||
`target.'cfg(target_os = "none")'`ããŒãã«ã¯ã`"os"`ãã£ãŒã«ãã`"none"`ã§ãããããªãã¹ãŠã®ã¿ãŒã²ããã«é©çšãããŸããç§éã®`x86_64-blog_os.json`ã¿ãŒã²ããããã®1ã€ã§ãã`runner`ããŒã¯`cargo run`ã®ãšãã«åŒã°ããã³ãã³ããæå®ããŠããŸãããã®ã³ãã³ãã¯ããã«ããæåããåŸã«ãå®è¡å¯èœãã¡ã€ã«ã®ãã¹ã第äžåŒæ°ãšããŠå®è¡ãããŸãã詳ããã¯ã[cargoã®ããã¥ã¡ã³ã][cargo configuration]ãèªãã§ãã ããã
|
||
|
||
`bootimage runner`ã³ãã³ãã¯ã`runner`ããŒãšããŠå®è¡ããããã«èšèšãããŠããŸãããã®ã³ãã³ãã¯ãäžããããå®è¡ãã¡ã€ã«ããããžã§ã¯ãã®äŸåããbootloaderãšãªã³ã¯ããŠãQEMUãç«ã¡äžããŸãããã詳ããç¥ããããšãããèšå®ãªãã·ã§ã³ã«ã€ããŠã¯[`bootimage`ã®Readme][Readme of `bootimage`]ãèªãã§ãã ããã
|
||
|
||
[Readme of `bootimage`]: https://github.com/rust-osdev/bootimage
|
||
|
||
ããã§ã`cargo run`ã䜿ã£ãŠã«ãŒãã«ãã³ã³ãã€ã«ãQEMUå
ã§èµ·åããããšãã§ããŸãã
|
||
|
||
## 次ã¯ïŒ
|
||
|
||
次ã®èšäºã§ã¯ãVGAããã¹ããããã¡ããã詳ããåŠã³ããã®ããã®å®å
šãªã€ã³ã¿ãŒãã§ãŒã¹ãæžããŸãããŸãã`println`ãã¯ãã®ãµããŒããè¡ããŸãã
|