ãã®èšäºã¯ ãããã£ã°ã«ãŒã Advent Calendar 2025 ããã³ Rust Advent Calendar 2025 ã·ãªãŒãº 1 ã® 9 æ¥ç®ã®èšäºã§ãã å¿ããæ¹åã Rust ã§ãã¡ãã³ã³ã® ROM ãäœãããšãããæ³å®å€ã«å€§å€ã ã£ããã©æ¥œããã£ãããšããã話ã§ãã mrustc + cc65 ãšããçµã¿åããã§ Rust ã³ãŒãããã¡ãã³ã³çšã«ã³ã³ãã€ã«ãããã£ã mrustc ãçæãã C ã³ãŒãã cc65 ã§ã³ã³ãã€ã«ããããã«ã²ãããéæ¹é æ¬ç©ã® libcore ãæ¹é ãã€ã€ã³ã³ãã€ã«ãéããšãããŸã§ãã£ãŠæå ãããåºæ¥äžãã£ããã€ããªã¯ 32KB ã®æ ã«å¯Ÿã㊠347KB ãªãŒããŒãšããè¡æã®çµæã«âŠ ãªã³ã« (ld65) ãéæ¹é ããŠäžèŠãªã·ã³ãã«ãåãããšããããäœã¬ã€ã€ãŒãåãããæ€é æçµçã«ã¯æå°éã® libcore ãå®è£
ãããšããããåããããšã«æå çŽäœæ²æãããŸãããããšãŠã楜ããåéºã§ããã ãŸããã¡ãã³ã³ã£ãŠã©ããªããŒãïŒ ãã¡ããªãŒã³ã³ãã¥ãŒã¿ (以äžãã¡ãã³ã³ãšåŒã³ãŸã) 㯠1983 幎ã«ä»»å€©å ããçºå£²ãããå®¶åºçšã²ãŒã æ©ã§ããæµ·å€çã® Nintendo Entertainment System ãšããååãã NES ãšãç¥ãããŸããä»ãã 40 幎以äžåã®ããŒããŠã§ã¢ã§ãããã¹ãŒããŒããªãªãã©ã¶ãŒãºããŒã«ãã®äŒèª¬ãªã©ãä»ãªãèªãç¶ãããåäœãæ°å€ãçã¿åºããäŒèª¬çãªãã©ãããã©ãŒã ã§ãã èªåãå
šã詳ãããªãã®ã§ãããã¹ããã¯ã¯ãããªæãã CPU: 8 bit ã§ MOS 6502 ããŒã¹ã®æ¹é ç (Ricoh 2A03) RAM: ããã 2KB ROM: ã«ãŒããªããžã«ããããä»å㯠32KB çšåºŠ ç»é¢è§£å床: 256Ã240 ãã¯ã»ã« çŸä»£ã®æèŠãããããšä¿¡ããããªãã»ã©å°ããã¹ããã¯ã§ããããã®å¶çŽã®äžã§åœæã®éçºè
ãã¡ã¯é©ãã¹ã工倫ãåãããŠã²ãŒã ãäœã£ãŠããã®ã§ãã…ã ãªãã§ããããšæã£ãã®ã ããæ¥ YouTube ãèŠãŠããããRust ã§ãã¡ãã³ã³ã®ãšãã¥ã¬ãŒã¿ãäœãåç»ã«åºäŒããŸããã é¢çœãããªã®ã§èªåããã£ãŠã¿ãããšæã£ãã®ã§ãããããã¡ãã£ãšåŸ
ãŠããšã äœã£ãŠããšãã¥ã¬ãŒã¿ã§åããããœãããæã£ãŠããªããã§ãããã ã ã£ããããã Rust ã§äœã£ãŠããŸãã°ããã®ã§ã¯ãªãã§ããããïŒ å€§æã®ãã¡ãã³ã³ã§çŸä»£ã®èšèªã§ãã Rust ãåããããããããšæããŸãããã ç§ã¯ããããæ°æã¡ã«ãªã£ãã®ã§ãã£ãŠã¿ãããšã«ããŸããã ãããã Rust ã§ãã¡ãã³ã³ã¯å¯èœãªã®ïŒ ã¢ãããŒãã¯äºéããããšæããŸãã ãŸã㯠LLVM ããŒã¹ã®ããã¯ãšã³ããäœããªãæ¢ããªãããŠãéåžžã® Rust ããŒã«ãã§ã€ã³ã®äžã§åããæ¹æ³ã ããäžã€ã¯ãäœããã®æ¹æ³ã§ Rust ããã©ã³ã¹ãã€ã«ããæ¢åã® 6502 çšã®ã³ã³ãã€ã©ã§ã³ã³ãã€ã«ããæ¹æ³ã§ãã ãŸããæ¢åã®ããŒã«ãã§ã€ã³ãæ¢ãæ¹æ³ãããéåžžãæ°ãããã©ãããã©ãŒã ãçšæãããªããã¡ããæ£æ»æ³ã«ãªãããã§ãã æåã«ç¢ºèªããã®ã¯ Rust ã® å
¬åŒãª Platform Support (Tier 1 ã 3) ã§ãã èŠãŸãããã¡ãã³ã³ã¯å«ãŸããŠããŸããããããããã ã ããããã³ãã¥ããã£ã«ããçŽ æŽããããããžã§ã¯ããããã€ãååšããããã§ãã ãŸãã llvm-mos ãšãã LLVM ããã¯ãšã³ãããããŸãã ãã¡ã㯠6502 系㮠CPU ãã¿ãŒã²ããã«ããŠããããã¡ãã³ã³ã§åäœãããäºäŸã玹ä»ãããŠããŸãã ããããã® ãªããžã㪠ã2 é±éåã«ãã³ãããããã£ãŠã¡ãã£ãšã³ã£ããããŸããã Rust ã¯åºæ¬çã« LLVM ãããã¯ãšã³ãã«ããŠããã®ã§ãããããããã° Rust ã³ãŒãã 6502 ç³» CPU åãã«ã³ã³ãã€ã«ããããšãå¯èœã§ãã å®éããããããŒã¹ã«ãã rust-mos ãšãããããžã§ã¯ããååšããŠãRust ããŒã«ãã§ã€ã³ã®æ§ç¯ãŸã§ã§ããŠãããã§ãããä»åã¯è©ŠããŠããŸããããå®çšçãªã¬ãã«ã®ç°å¢ãæ±ããã®ã§ããã°ãã¡ãã®æ¹ãè¯ããããªé°å²æ°ããããŸãã ããäžã€ã¯ãRust ãäœããã®èšèªã«ãã©ã³ã¹ãã€ã«ããŠãããã 6502 çšã®ã³ã³ãã€ã©ã§ã³ã³ãã€ã«ããæ¹æ³ã§ãã ãã®å Žåã第äžéžæè¢ã¯ã³ã³ãã¥ãŒã¿çã®æšæºèªã§ãããšããã® C èšèªã§ãã ãããŠãå®ã¯ããã«ã¡ããã©è¯ããããžã§ã¯ããååšããŠããŸããã mrustc : Rust â C ãžã®ãã©ã³ã¹ãã€ã© cc65 : C â 6502 çšã®ã³ã³ãã€ã© ç¹ã« cc65 ã¯ãã¡ãã³ã³çš ROM ãäœãçéã§ã¯æåãªããã§ãæ¥æ¬èªã§ã®è§£èª¬ããµã³ãã«ã³ãŒããæ
å ±ã倿°ãããŸãã ã©ã¡ãã®ã¢ãããŒãããšããèããã®ã§ãããåŸè
ã®æ¹ãç§ã«ãšã£ãŠã¯åãçµã¿ãããã®ã§ã¯ãªãããšæããŸãããäœãããŸãåããªãããšããã£ããšããŠããC èšèªãäžéèšèªã«ããŠããã°äœãèµ·ããŠãããèªãã°ããããã§ãã ãšããããšã§ãä»å㯠mrustc + cc65 ã®çµã¿åããã§ Rust ã³ãŒãããã¡ãã³ã³çšã«ã³ã³ãã€ã«ããããšãç®æãããšã«ããŸããã Q: ã§ã C èšèªçµç±ããã®ããããªãã§ããïŒ Rust ã§æžããã£ãŠèšããã®ïŒ A: ããããšæããŸãããã§ãæçµ Rust ã ãæžããŠæ©æ¢°çåŠçã ãã§åãã£ãŠèããã Rust ã§æžããã£ãŠèšãããšæããŸãããïŒ ç§ã¯ããèšã匵ããŸãã mrustc ãšã¯ mrustc ã¯ãrustc ãããŒãã¹ãã©ããããããšãç®æšã« C++ ã§æžããã Rust ã³ã³ãã€ã©ã§ãã è¥å¹²è©±ãéžããŠããŸããŸãããå
¬åŒã® Rust ã³ã³ãã€ã©ã§ãã rustc èªèº«ã¯ Rust ã§æžãããŠããŸãããã®ãã Rust ãã³ã³ãã€ã«ããã®ã«ã¯ Rust ã³ã³ãã€ã©ãå¿
èŠã§ãïŒ ããã¯å°ããŸããããããã®äžãããã¹ãŠã® Rust ã³ã³ãã€ã©ãæ¶æ»
ããŠããŸã£ãããããäžåºŠ Rust ã³ã³ãã€ã©ã䜿ããããã«ãªããŸã§ã«ã¯çžåœãªéã®ããå¿
èŠã«ãªã£ãŠããŸããŸãã ã¡ãªã¿ã«ããã®äœæ¥ãã³ã³ãã€ã©ã®ããŒãã¹ãã©ãããšåŒã¶ãããã§ãã ããã§ mrustc ãããã°ãC++ ã³ã³ãã€ã©ããããã° Rust ã³ã³ãã€ã©ãåæ§ç¯ã§ããããã«ãªã£ãŠäŸ¿å©ãšããããã§ãã ããã«è±ç·ããŸããããããããã® gcc ãã Linux ãããŸã§äžç·ã«æ¶ãé£ãã ãåæ§ç¯ã¯ã§ããªãã®ã§ããããïŒ ããã«ã€ããŠã¯ live-bootstrap ãšãããããžã§ã¯ããªã©ããã£ãŠãæã§æžããå°ããæ©æ¢°èªããã¢ã»ã³ãã©ã GCCãcoreutils ãªã©ãçµãŠ OS ãåæ§ç¯ããæé ãäžå¯§ã«è§£èª¬ãããŠããŸããããã¯ç°äžç転çã«åããŠèŠããŠããã®ãè¯ããããããŸããããã£ãšçŸä»£çãªã³ã³ãã¥ãŒã¿ç°å¢ãåæ§ç¯ã§ããããšã§ãããããœãŒã¹ã³ãŒããéã£ãŠããã°ãã§ãã…ã è©±ãæ»ããŸãããã ãã㪠mrustc ã®ããŒã«ãšããŠã®äžçªã®ç¹åŸŽã¯ããããŸã§ã valid 㪠Rust ã³ãŒããã³ã³ãã€ã«ã§ããããšãæéèŠèŠããŠããããšããç¹ã§ããéã« invalid 㪠Rust ã³ãŒãããã£ããã³ã³ãã€ã«ã§ããŠããŸã£ãŠãããŸãæ°ã«ããŸãããäŸãã°… ã©ã€ãã¿ã€ã æ€æ»ãããªã ã³ã³ãã€ã«ãšã©ãŒã¯ãæ¬æ¥ã³ã³ãã€ã«ãéãã¯ãã®ã³ãŒããªã®ã§ mrustc ã®ãã°ã§ããããšèãã蚺æã¯äžå¯§ã§ã¯ãªã ãã®å²ãåãã¯ç®æšãã¶ããŠããªããŠãããªãšæããŸããããã®ããããã³ã³ãã€ã«ãšã©ãŒãçºçãããšãã®èª¿æ»ã¯è¥å¹²é£ãããšãããããŸããã ãã ãä»åç§ã«ãšã£ãŠã®äœããã®éèŠãã€ã³ãã¯ãmrustc ããã€ããªã§ã¯ãªã C èšèªã®ã³ãŒããåºåãããšããç¹ã§ãã ããã¯ãããã mrustc èªèº«ã®ã³ã³ãã€ã«ã« C++ ã䜿ãã®ã§ãåãã³ã³ãã€ã©ã§ C ã³ãŒããã³ã³ãã€ã«ã§ããŠããŒãã¹ãã©ããäžäŸ¿å©ãšããæå³ãªã®ã§ãããã ä»åã¯ãã®ç¹é·ãçãããŠé«çŽãªãã©ã³ã¹ãã€ã©ãšããŠäœ¿ãããŠããã ããŸãã ãããŠããã® C èšèªã³ãŒãã cc65 ã§ã³ã³ãã€ã«ããããšãç®æããŸãã cc65 ãšã¯ cc65 ã¯ããã¡ãã³ã³ã«æèŒãããŠãã MOS 6502 ç³» CPU ãã¿ãŒã²ãããšãã C ã³ã³ãã€ã©ããŒã«ãã§ã€ã³ã§ãã Apple II ã Commodore PETããããŠãã¡ãããã¡ãã³ã³ãªã©ã6502 ç³» CPU ãæèŒããããŒããŠã§ã¢ã§åããœãããŠã§ã¢ã®éçºã«åºã䜿ãããŠããŸãã C99 ã®äžéšæ©èœã«å¯Ÿå¿ããŠãããã³ã³ãã€ã© (cl65) ãã¢ã»ã³ãã© (ca65) ããªã³ã« (ld65) ã«å ãããã£ã¹ã¢ã»ã³ãã© (da65) ããªããžã§ã¯ããã³ã (od65) ãŸã§äœã§ãäžéãããŒã«ãããã£ãŠããŸãã ãŸãããã¡ãã³ã³åãã®ã¡ã¢ãªé åèšå®ãæšæºã§ä»å±ããŠãããã¡ãã£ãšããæšæºã©ã€ãã©ãªãåããŠããã®ã§ãæåãåºåããã ãã® ROM ãªãæ¬åœã«ããã«äœããŠããŸããŸãã èªåã§å®è£
ããããšæããš CHR ãã¡ã€ã«ã«ãã©ã³ãã®ãããããããçšæã㊠PPU ã¬ãžã¹ã¿ãæäœããŠâŠ ãšå€§å€ãããã§ãããcc65 ã®ã©ã€ãã©ãªã䜿ãã°ãªããš cprintf() 颿°äžçºã§ãªããã«ç»é¢ã«æåãåºãããšãã§ããŸãã ãã¡ãã³ã³éçºã«ãããŠã¯ cc65 ã¯å®çªããŒã«ã®äžã€ãšãªã£ãŠããããã§ãç¹ã«æ¥æ¬èªã®è§£èª¬èšäºããµã³ãã«ã³ãŒããè±å¯ã«ååšããŸããä»åãã¡ãã³ã³åææŠãªã®ã§ããã¯ãããããã§ãã C ã³ã³ãã€ã©ã®åè£ãšããŠã¯å
ã»ã©ã® llvm-mos ã®ææç©ã§ãã clang ã ã䜿ãããŠããã ãæããããšæãã®ã§ãããä»åã¯ãã®ãæè»œããæ±ºãæãšãªããcc65 ãæ¡çšããããšã«ããŸããã é 匵ã£ãŠ mrustc ãåºåãã C ã³ãŒããã³ã³ãã€ã«ã§ããããã«ãªã£ãŠãããããšæããŸãã ã¬ã®ã¥ã¬ãŒã·ã§ã³ ããŠãå®éã«äœæ¥ãå§ããåã«ãã©ããŸã§ã§ããããæåããšãããã®ã¬ã®ã¥ã¬ãŒã·ã§ã³ã決ããŠãããŸãã Rust ã ãã§æžãããã³ãŒãã«æ©æ¢°çãªåŠçã ããè¡ããäœããããã¡ãã³ã³ãšãã¥ã¬ãŒã¿ã§åãã° OK ãšããŸãã cc65 ã«å
¥ã£ãŠããã©ã€ãã©ãª (äŸãã° cprintf() ) ã¯äœ¿ã£ãŠè¯ãããšã«ããŸãã åããããéšåãåãã° OK ã§ãä»»æã® Rust ã®èšèªæ©èœãåãå¿
èŠã¯ãããŸããã Q: 2 çªç®ãš 3 çªç®ãããããªãã§ããïŒ A: ããããããšã¯æããŸãããã§ãäœã¬ã€ã€ãŒåãããªãããŠãPPU ã®åæåãšãå²ã蟌ã¿ãšããã¢ã»ã³ããªã¬ãã«ã§ææžããããšãããå€ãªãšããã§æ²Œããããªäºæããããã§ããæè¡ãã€ããããã€ãåãã£ã¬ã³ãžãããããããŸããã ãšã¯ãããæçµææç©ã®ããã«èªåã§æžãã³ãŒãã¯ãã¹ãŠ Rust ã§ãããšã¯æ©æ¢°çãªå€æã ãã§åãããšããæ¹éã ãã¯è²«ããããšæããŸãã cc65 ãš mrustc ã®åäœç¢ºèªããã ããŠããŸã㯠cc65 ãš mrustc ãããããã¡ãããšåãããšã確èªããŠãããªããšå§ãŸããŸããã cc65 ã§ãã¡ãã³ã³çš ROM ãäœã£ãŠã¿ã cc65 ã¯äœ¿ãã ããªããªããš apt ã§ã€ã³ã¹ããŒã«ã§ããŸãã apt install cc65 ãŸãã¯è©Šãã« “Hello, World!” ã衚瀺ããããã°ã©ã ãæžããŠã¿ãŸãããã #include <conio.h> int main(void) { cprintf("hello, world!"); while (1); // ç¡éã«ãŒãã§çµäºããªãããã«ãã } ããã cl65 -t nes hello_world.c ã§ã³ã³ãã€ã«ãããšããã£ãšããéã« hello_world ãšãã ROM ãã¡ã€ã«ãçæãããŸãã ããããã ROM ã§ãã hello_world.nes ãšããååã«ããŠãšãã¥ã¬ãŒã¿ã§å®è¡ããŠã¿ããšç»é¢ã« “Hello, World!” ãšè¡šç€ºãããŸããããã£ããªããã©ãã§ããã§ã«ã¡ãã£ãšããããã ãªãä»åãã¹ã¯ãªãŒã³ã·ã§ããã«ã¯ MERU ãšãã Web äžã§åããšãã¥ã¬ãŒã¿ã䜿ãããŠããã ããŠãããŸãããªããšãã¡ãã®ãšãã¥ã¬ãŒã¿ã Rust ã§æžãããŠããããã§ãã mrustc ããã«ããã ç¶ã㊠mrustc ãããŠã³ããŒãããŠãã«ãããŠã¿ãŸãã git clone https://github.com/thepowersgang/mrustc cd mrustc make -f minicargo.mk ãããé©ãã»ã©ãã£ãããšãã«ããå®äºããŸããã çæãããã®ã¯ä»¥äžã®ãã®ã§ãã mrustc : rustc ã®ä»£æ¿ãšãªãã³ã³ãã€ã©æ¬äœ minicargo : cargo ã®ä»£æ¿ãšãªããã«ãããŒã« æšæºã©ã€ãã©ãªã®ãªããžã§ã¯ããã¡ã€ã« ã¡ãªã¿ã«ãã®ç¶æ
ã§ãã«ãããããªããžã§ã¯ããã¡ã€ã«ã¯ããã¹ããã·ã³ã®åã C ã³ã³ãã€ã©ã䜿ã£ãŠçæããããã€ããªã§ãããªã®ã§ãããã¹ããã·ã³ã§åã Rust ããã°ã©ã ã¯ã³ã³ãã€ã«ã§ããç¶æ
ã«ãªã£ãŠããã¯ãã§ãã詊ããŠã¿ãŸãããã fn main() { println!("Hello, world!"); } å®è¡ããŸãã $ mrustc hello.rs && ./hello Hello, world! åé¡ãªãã§ããã ã¡ãªã¿ã«ãã®ãšãçæããã C ã³ãŒã㯠324 è¡ãããŸããã 軜ãçºããŠã¿ããšãããŒã ãã³ã°ãªã³ã°ããã倧éã®é¢æ°ãååãæ¶å»ããã倿°åãMIR ã圷圿ãšããã bb1: , bb2: ãšãã£ãã©ãã«ããããŠå€§éã® goto æãèŠãããŸãã ããã«ãæ©æ¢°çæãããã³ãŒããšããæãã§ãããæã
ã«å
ã®ååãªã©ãã³ã¡ã³ãã§æ®ããŠãããŠããã®ãè¯å¿çã§ãæå€ãšèªã¿ããããã§ãã â Rust ã® main() 颿°ãã³ã³ãã€ã«ãããšæãããéšå // ::"bin#"::main void ZRG1cD3bin4main0g(void) // -> () { tUNIT rv; struct s_ZRG2cE9core0_0_03fmt9Arguments0g var1; // ::"core-0_0_0"::fmt::Arguments<'static,>/*S*/ struct e_ZRG2cE9core0_0_06option6Option1gBsSG4c_A3fmt2rt2v18Argument0g var2; // ::"core-0_0_0"::option::Option<&'static [::"core-0_0_0"::fmt::rt::v1::Argument/*S*/],>/*E*/ SLICE_PTR var3; // &'static [&'static str] SLICE_PTR var4; // &'static [::"core-0_0_0"::fmt::ArgumentV1<'static,>/*S*/] var3 = make_sliceptr(&ZRG2cD3binB_09FRAGMENTS0g.val, 0x1ull); // _3 = MakeDst(&::"bin#"::#0::FRAGMENTS, 0x1 usize) var4 = make_sliceptr(&ZRG1cD3binF6const00g.val, 0x0ull); // _4 = MakeDst(&::"bin#"::const#0, 0x0 usize) memset(&var2, 0, sizeof(struct e_ZRG2cE9core0_0_06option6Option1gBsSG4c_A3fmt2rt2v18Argument0g )); // _2 = Variant(::"core-0_0_0"::option::Option<&'static [::"core-0_0_0"::fmt::rt::v1::Argument/*S*/],> #0, {}) var1._0 = var3; var1._1 = var2; var1._2 = var4; // _1 = Struct(::"core-0_0_0"::fmt::Arguments<'static,>, {_3, _2, _4}) ZRG3cD8std0_0_02io5stdio7__print0g( var1 ); // ^ Call( _0 = ::"std-0_0_0"::io::stdio::_print<'static,>( _1, ), bb1, bb2) /* ZST assign */ return ; // ^ Return bb2: _Unwind_Resume(); // Diverge } ããŠãããããã®ããŒã«ãåãããšã¯ç¢ºèªã§ããŸããã ãããããæ¬çªã§ãã mrustc ã®åãåºãã³ãŒãã cc65 ã§ã³ã³ãã€ã«ãã ãããã mrustc ãåºåãã C ã³ãŒãã cl65 ã§ã³ã³ãã€ã«ããŠã¿ãŸãã cl65 ã察å¿ããŠããªãã³ãã³ãã©ã€ã³ãªãã·ã§ã³ãããŸããã©ãããŒã¹ã¯ãªããã ãæã¿ããã以å€ã¯çŽ ã®ç¶æ
ã§ãŸã詊ããŠã¿ãŸãã æ©éèªåã§æžããã³ãŒããã³ã³ãã€ã«ããããšããã§ãããå®ã¯äœãããå
ã«ã³ã³ãã€ã«ããªããã°ãªããªããã®ããããŸããcore ãšãã crate ã§ãã æ¥ã«åºãŠããŠãªãã ãšæããããšæããŸããããã㯠Rust ã®æšæºã©ã€ãã©ãªã®äžéšã§ãã Rust ã®æšæºã©ã€ãã©ãªã¯ãå®ã¯ä»¥äžã®ãããªè€æ°ã® crate ã«ãã£ãŠæ§æãããŠããŸãã core : æå°éã®èšèªã®ã³ã¢æ©èœãéããå°ããã©ã€ãã©ãªãããªããã£ãåã®ã¡ãœããã¯ãã¡ãããååæŒç® ( Add , Sub , Mul , Div ) ã Iterator , Sized ãšãã£ãã³ã³ãã€ã©ãç¹å¥æ±ããããã¬ã€ãã®å®äœãããã«ãããOS ãããŒãã¢ãã±ãŒã·ã§ã³ã«äŸåããªããçŽç²ãªèšèªæ©èœã ããæäŸããã alloc : ã¡ã¢ãªã¢ãã±ãŒã·ã§ã³ãå¿
èŠãªæ©èœãæäŸããã©ã€ãã©ãªã Vec , String , Box ãªã©ãããã«å«ãŸãããOS ã»ã©ãªãããªæ©èœã¯ãªããã¢ãã±ãŒã¿ããããªãäœããããšããç°å¢ã§äŸ¿å©ã std : OS æ©èœãå«ãããã«æ©èœã®æšæºã©ã€ãã©ãªããã¡ã€ã« I/Oããããã¯ãŒã¯ãã¹ã¬ãããªã©ãéåžžã®ã¢ããªã±ãŒã·ã§ã³éçºã§å¿
èŠãªæ©èœããã¹ãŠæã£ãŠããã core ãš alloc ã®äžã«äœãããŠãããäž»èŠãªèŠçŽ ã re-export ããŠãããŠããããã®ãããç§ãã¡ã¯èåŸã«ãã core ãš alloc ãæèããã std::ops::Add ã std::string::String ãšããŠåç
§ã§ããŠããã çµã¿èŸŒã¿ããã°ã©ãã³ã°ã§ã¯ãªãã㪠OS ãµããŒãããªãããšãããã®ã§ã #![no_std] ãšãããã©ã°ãã€ããŠæšæºã©ã€ãã©ãªãåãé¢ãããšãå€ããšèããŸãã ããã core ãå€ãããšã¯éåžžãããŸãããcore 㯠Rust ãæ£æ°ãä¿ãŠãæåŸã®ã©ã€ã³ã§ããããããå€ããšæ¬åœã«æåéãäœãã§ããªããªã£ãŠããŸããŸãããã®ãããä»åã cl65 ã§ core ãã³ã³ãã€ã«ã§ãããšããããŸãç®æãå¿
èŠããããŸãã ããŠãcore crate ã mrustc ã§ã³ã³ãã€ã«ã㊠C ãã¡ã€ã«ãäœããšãããŸã§ã¯ããã¹ããã·ã³åãã®åŠçãšäžç·ãªã®ã§ç¹ã«åé¡ã¯ãããŸãããæãã㊠libcore.rlib.c ãšããåäžã® C ãã¡ã€ã«ãåŸãããŸããã åé¡ã¯ããããããã®ãã¡ã€ã«ã cl65 ã¯ã³ã³ãã€ã«ã§ããã§ããããã ããããããªããæåã®ã³ã³ãã€ã«ã詊ããŠã¿ãçµæããã¡ãã§ãã --- BUILDING core v0.0.0 (0.0% 1r,0w,12b,0c/13t) > /workspace/mrustc-master/bin/mrustc /workspace/mrustc-master/rustc-1.29.0-src/src/libcore/lib.rs -o output/libcore.rlib -C emit-depfile=output/libcore.rlib.d --cfg debug_assertions -O -L output --crate-name core --crate-type rlib --crate-tag 0_0_0 > output/libcore.rlib_dbg.txt (0.0% 1r,0w,12b,0c/13t): core v0.0.0 /workspace/mrustc-master/rustc-1.29.0-src/src/libcore/slice/mod.rs:1947-1948 warn:0:Unexpected attribute rustc_on_unimplemented on impl /workspace/mrustc-master/rustc-1.29.0-src/src/libcore/slice/mod.rs:1960-1961 warn:0:Unexpected attribute rustc_on_unimplemented on impl output/libcore.rlib.c(9): Error: Include file 'stdatomic.h' not found output/libcore.rlib.c(12): Error: Include file 'math.h' not found output/libcore.rlib.c(22): Error: Identifier expected output/libcore.rlib.c(22): Warning: Implicit 'int' is an obsolete feature output/libcore.rlib.c(22): Error: ';' expected output/libcore.rlib.c(26): Warning: Implicit 'int' is an obsolete feature output/libcore.rlib.c(26): Error: ';' expected output/libcore.rlib.c(27): Warning: Implicit 'int' is an obsolete feature output/libcore.rlib.c(27): Error: ';' expected output/libcore.rlib.c(28): Error: Identifier expected output/libcore.rlib.c(28): Warning: Implicit 'int' is an obsolete feature output/libcore.rlib.c(28): Error: ';' expected output/libcore.rlib.c(28): Warning: Implicit 'int' is an obsolete feature output/libcore.rlib.c(28): Error: ';' expected output/libcore.rlib.c(28): Warning: Implicit 'int' is an obsolete feature output/libcore.rlib.c(28): Error: ')' expected output/libcore.rlib.c(28): Warning: Implicit 'int' return type is an obsolete feature output/libcore.rlib.c(28): Error: '{' expected output/libcore.rlib.c(28): Fatal: Too many errors C Compiler failed to execute - error code 256 ⊠ãã®ã28 è¡ç®ã§è«Šãããããå°ããŸããmrustc ãåãåºãã C ã³ãŒãã¯ãŸã 28 äžè¡ããããã§ããã©âŠ ãŸãæåã¯ãããªãã®ã§ããã… cl65 ã§ã³ã³ãã€ã«ã§ããããã«ãããåã 现ãããã®ã¯é€ããŠãäž»ãªåå ã¯æ¬¡ã®ãããªæãã§ãã ç¹å®ã®ã³ã³ãã€ã© (gcc ãŸã㯠MSVC) ã«äŸåããã³ãŒããçæãããŠããã __builtin_* ç³»é¢æ°ãšãã zero-sized array ãšãã cl65 ã察å¿ããŠãã C æšæºãè¥å¹²å€ãã C99 ã®ããããã«å¯Ÿå¿ããŠãããšã®ããšã§ãããè¶³ããªããã®ãå€ãã£ãã§ãã ç°¡åãªãšããã§ã¯ for ã®äžã§ã®èå¥åå®çŸ© for (int i = 0; ...) ããããªã®ã ãš designated initializer struct X x = { .member = value } ãšãã ããªããã£ãåãéå®ãããŠããã cc65 (6502 CPU) ã«ã¯ float, double ãµããŒãããããŸããã æŽæ°åã (u)int32_t ãŸã§ãããããŸããã Rust ã§ãããš i64, u64, i128, u128 ããµããŒãã§ããŸããã ç¹ã« u64 㯠core::any::TypeId ã§å¿
èŠã«ãªãã®ã§é¿ããããªãã®ã§ãããé¿ãããããããŸããã ã¢ãã¬ã¹ç©ºéã 16 bit ãããªãã ãããšé¢é£ããŠãã¢ã»ã³ãã© (ca65) ãçšæããã©ãã«çšã®é åãåèš 16 bit = 32768 ååããçšæãããŠãããã28 äžè¡ãšããã³ãŒãããŒã¹ã«èããããªããŠãªãŒããŒãããŒããŠããŸããŸããã ããŒã«ã«å€æ°é åã®ãµã€ãºãå°ãªãã ã¡ã¢ãªãå°ããã®ã§ããŒã«ã«å€æ°ãããããé
眮ããã®ã¯ç¡çã§ãã 調æ»ã®æ®µéã§ core::hash ã®äžã§èšç®çšã« 1024 ãã€ãã®é
åããšã£ãŠããã³ãŒããçºèŠãé©ããªã©ããŸãããçŸä»£ã® PC ã¯å€§å¯è±ªã§ããã ã»ãšãã©ã¯ mrustc ã®ã³ãŒãçæã®ä¿®æ£ã§ãããã ãã©ãã«äžéãªã©ã¯ã¢ã»ã³ãã© (ca65) ããªã³ã« (ld65) ã®ä¿®æ£ãå¿
é ã«ãªããŸãããfloat çã®ãµããŒãããªãåé¡ã«ã€ããŠã¯ core ã©ã€ãã©ãªåŽã®ä¿®æ£ãå¿
é ã§ããã ãšãããããŸãäžæŠã¯ã³ã³ãã€ã«ãéããšãããç®æãããã®ããã«æŽæãšããæŽæãããšããéæ¹é ããŸãã typedef int float; ãªããŠä»åŸæžãããšã¯ãªãã§ãããã… è©Šè¡é¯èª€ã®æ«ããªããšãéæ¹é cc65 ã§éæ¹é core ãã³ã³ãã€ã«ã§ãããŸã§ã«ã¯è³ããŸããã ãŽãŒã«ãéè¿ã«æããŸãã ããããã¯åçŽãªãŠãŒã¶ãŒããã°ã©ã ãã³ã³ãã€ã«ã§ããã°è¯ãã¯ãã§ããæåã® C ãšã»ãŒåæ§ãªãåçŽãªããã°ã©ã ãã³ã³ãã€ã«ããŠã¿ããšãã⊠#![feature(no_core)] #![no_core] #![no_main] extern "C" { #[no_mangle] fn gotoxy(x: u8, y: u8); #[no_mangle] fn cprintf(fmt: *const u8, ...); } #[start] fn start(_argc: isize, _argv: *const *const u8) -> isize { cprintf(b"hello\0" as *const u8); loop {} } ⊠ãªããšã以äžã®ããã«ãªã³ã¯æã«ãšã©ãŒã«ãªã£ãŠããŸããŸããã ... (äžç¥) ... output/main.c(252): Warning: '__mrustc_op_and_not32' is defined but never used ld65: Warning: /workspace/cc65/cc65-2.19/cfg/nes.cfg(15): Segment 'CODE' overflows memory area 'ROM0' by 356168 bytes ld65: Error: Cannot generate most of the files due to memory area overflow C Compiler failed to execute - error code 256 Process exited with non-zero exit status 1 FAILING COMMAND: /workspace/mrustc-master/bin/mrustc /workspace/rust-hello-nes/main/src/main.rs -o output/main -C emit-depfile=output/main.d --cfg debug_assertions -O -L output -L output/host --crate-name main --crate-type bin --crate-tag 0_1_0 --target ./target.toml --extern core=output/libcore.rlib Env: OUT_DIR=/workspace/rust-hello-nes/output/build_main-0_1_0 CARGO_MANIFEST_DIR=/workspace/rust-hello-nes/main CARGO_PKG_NAME=main CARGO_PKG_VERSION=0.1.0 CARGO_PKG_VERSION_MAJOR=0 CARGO_PKG_VERSION_MINOR=1 CARGO_PKG_VERSION_PATCH=0 (100.0% 0r,0w,0b,2c/2t): æ°ããããã°ã©ã ãµã€ãºã ROM äžã®é åã 347 KB ã»ã©è¶
éããŠããŸã£ããšã®ããšã æå
ã® nes.cfg ã«ããã°ã0x7FFA = 32762 ãã€ããã€ãŸãçŽ 32 KB ããååšããŸããã ãŽãŒã«ãé ããã£ãŠããé°å²æ°ãæããŸãããããŸãã«ããããŸãã§ç¬ã£ãŠããŸããŸããã ld65 (ãªã³ã«) ãæ¹é ããŠäžèŠãªã·ã³ãã«ãèœãšããããã«ãã (倱æ) ãªããããªã«ãµã€ãºã倧ããã®ããåå ã¯æããã§ãããcore crate ã¯ãã®æç¹ã§äžã€ã®ãªããžã§ã¯ããã¡ã€ã«ã§ãã libcore.rlib.o ã«ãªã£ãŠããã®ã§ãããããã«ã¯ core ã«ãããã¹ãŠã®å®è£
ãå
¥ã£ãŠããããã§ãã ãã㊠ld65 ã«ã¯ãªã³ã¯ææé©åã®ãããªãã®ããªãã®ã§ã䜿ããããªã颿°ãå«ããŠãã¹ãŠãã³ãã«ããããšããŠããããã§ãããããªããš ROM ã«ã¯å°åºåãŸããªããšããããšã§ããã ããããæé©åããªãã®ã§ããã°ãæé©åãäœãã°è¯ãã®ã§ã¯ãªãã§ããããã od65 ã«ããã°ãå§åçã«å€§ããã®ã¯ç¢ºãã« CODE ã»ã°ã¡ã³ãã§ãã ãšãªãã°ãã¹ã¿ãŒãã¢ããã«ãŒãã³ãã exports ã®äŸåé¢ä¿ããªãŒãäœããåç
§ãããŠããªããã®ãåé€ããã°è§£æ±ºã§ããããªæ°ãããŸãããªã³ã«ã®éæ¹é ã®å§ãŸãã§ãã $ od65 --dump-segments ./output/libcore.rlib.o Segments: Count: 6 Index: 0 Name: "CODE" Flags: 0 Size: 416728 Alignment: 1 Address size: 0x02 (absolute) Fragment count: 280296 Index: 1 Name: "RODATA" Flags: 0 Size: 12346 Alignment: 1 Address size: 0x02 (absolute) Fragment count: 8758 Index: 2 Name: "BSS" Flags: 0 Size: 51 Alignment: 1 Address size: 0x02 (absolute) Fragment count: 51 Index: 3 Name: "DATA" Flags: 0 Size: 3308 Alignment: 1 Address size: 0x02 (absolute) Fragment count: 2104 Index: 4 Name: "ZEROPAGE" Flags: 0 Size: 0 Alignment: 1 Address size: 0x01 (zeropage) Fragment count: 0 Index: 5 Name: "NULL" Flags: 0 Size: 0 Alignment: 1 Address size: 0x02 (absolute) Fragment count: 0 ä»ãŸã§ç¹ã«ã¢ã»ã³ããªãçŽæ¥è§Šã£ãŠäœããããããšã¯ãããŸããã æåã¯å逿¡ä»¶ãå³ããããããŠããŸãäœãããªã ROM ãã§ãããã£ãŠããŸããŸããã ããããã ãããšãã£ãŠããå°ãä¿å®çã«ãããšãçµå± ROM ãµã€ãºã 150KB çšåºŠã«ããå°ããã§ããŸããã§ãããããã§ã¯çµå±ãªãŒããŒããŠããŸãããšã«å€ãããããŸããã ãããã°åºåãèŠãéããŸã ãŸã äžèŠãªã·ã³ãã«ãè©°ã蟌ãã§ããããªã®ã§ãå€åæåã®ã¹ã¿ãŒãã¢ããã«ãŒãã³ãšããŠããŒã¯ããŠããç¯å²ã倧ãããããšããäœãééã£ãŠããã ãšæããŸãã ãšããããã詊è¡é¯èª€ããŠããã®ã§ãããæ¬¡ç¬¬ã« export å¢çã®å€å¥ãšããåé¡ãããªãé£ããããšã«æ°ã¥ãå§ããŸããã C ã Rust ç±æ¥ã®æ®éã®é¢æ°ã¯ãŸã ããã®ã§ãã ãšããã®ããã³ã³ãã€ã©ããã¡ããš .proc – .endproc ãšãããã®ã§é¢æ°ãå²ãã§çæããŠãããããã§ããããããŠããã°ã¢ã»ã³ãã©ã .o ãã¡ã€ã«ã«ãã®ãŸãšãŸãã®ãµã€ãºãäžç·ã«æžã蟌ãã§ãããŸãã ãã®ãããç¹å®ã®é¢æ°ãå¥ã®äœãåç
§ããŠããã®ãã¯ããã®ãµã€ãºã®ç¯å²å
ã§ã©ãã« jmp ããŠããã®ãã調ã¹ãã°ãããåé€ã決ãããšããã©ãããäœãã€ãåé€ããã°ããã®ãæ¯èŒç容æã§ããã äžæ¹ãçŽæ¥ã¢ã»ã³ããªã§æžãããŠãã颿° (ã©ãã«) ãã¡ã¯èªç±å¥æŸã§ãã åŠçã®ã©çãäžã«ã©ãã«ãã€ããŠããŠå€ããæšªå
¥ããããããªããšãããã¿ããã§ãããæ¥µãã€ãã¯èªå·±æžãæãã³ãŒããªãååšã§ãã æåã« jmp $0000 ãšããåœä»€ãèŠããšãã¯éŠãããããŸãããããããã©ããæ¬åœã« 0 çªå°ã«å
¥ã£ãŠããã¢ãã¬ã¹ã«é£ã³ããããã§ã¯ãªããããã®ã§ãããã®åœä»€ã«å°éããåã«ãã¡ããã©ãã®ãªãã©ã³ãã«ãããã³ãŒãé åã®ã¡ã¢ãªãäžæžãããŠäœ¿ããããã§ãã ã€ãŸãã jmp åœä»€ã«å°éããåã« store ç³»ã®åœä»€ãã€ããã $0000 ãšãããªãã©ã³ãããèªäœãæžãæããŠããŸããšããããšã§ããããããš CPU ã jmp åœä»€ã«å°éãããšãã«ã¯ãããæåãã jmp $1234 ãšæžãããŠãããã®ããã«æžãæãã£ãŠãããšã®ããšã§ãããªã«ããæãã ãããªããšã©ãããã©ããŸã§ãäžã€ã®ã颿°ããªã®ã倿ããã«ã¯ã究極çã«å®è¡ãã·ãã¥ã¬ãŒã·ã§ã³ããå¿
èŠãããããã§ããåå²ãªã©ãããã§ããããããšãã§ããªãããšã«ãªãã§ãããããããããã©ãããã¹ããŒãã§ãã®åŠçã«äŸµå
¥ãããã«ãã£ãŠè«å€§ãªãã¿ãŒã³ããããŸããä»®ã«ãããä¹ãè¶ããŠãªããšãç¯å²ãåãã£ããšããŠãããããé©åœãªäœçœ®ã«ã¡ãããšãªãã±ãŒã·ã§ã³ã§ããã®ããæªãããªã£ãŠããŸããã çµå±ãæéåãããã£ãŠããã®ã¢ãããŒãã¯æå¿µããããšã«ãªããŸããã æ¢åã®ãªã³ã«ã®æé©åã¯ã©ããªã£ãŠããã§ãããããæ¬åœã«ãããã§ããã 諊ããŠå¿
èŠãªéšåã ã core ãäœã ãªã³ã¯ææé©åãç¡çãªã®ã§ããã°ãçºæ³ã転æãããããããŸããã ã€ãŸãç§ãæé©åãããŸããå¿
èŠãªå®è£
ã ããå«ãæå°éã® libcore ãæžããŠãªã³ã¯ããã°æäœéåããããšã¯ã§ããã¯ãã§ãã èšèªæ©èœã«å¿
èŠãª marker trait ( Sized , Copy ãã¡) ãªã©ãå«ãããšå¿
èŠãªå®è£
ã¯æã£ãããå€ãã®ã§ãããäŸãã°ååæŒç®ã¯ u8 ã ãã«å®çŸ©ãããªã©ã®æ¶ããŸããåªåã«ãã£ãŠããšã«ããæå°æ§æãç®æããŸããã ãããŠå床ã³ã³ãã€ã«ããŠã¿ããšâŠ $ make ... äžç¥ ... Completed welcome v0.1.0 [bin welcome] (100.0% 0r,0w,0b,3c/3t): ãã£ãšãã³ã³ãã€ã«ãéããŸãããé·ãã£ãã⊠ãã¡ã€ã«ãå°ãããªã£ãã®ã§ cc65 ã¯ç¡æ¹é ã§ãããããã«ãªããšãã坿¬¡ç广ããããŸãã é åããããŸããããããã«ããŠã core crate ãã®ãã®ãæžããªããŠããçµéšã¯ãªããªãã§ããªãã®ã§ãçµæ§æ¥œããã£ãã§ãã Rust 䜿ããªããããªããã£ãåã« impl [T] {} ãšãããŠã¿ãããšäžåºŠãããã¯æã£ãããšããããšæãã®ã§ãããããããŸãã«å¶ãç¬éã§ããã ã§ãããã® æåŸã«ããã¡ãã£ãšã©ã€ãã©ãªãæŽçããŠèŠãç®ãæŽããŠããããªæãã®ãœãŒã¹ã³ãŒããå®è¡ã§ããããã«ãªããŸããã #![feature(no_core)] #![no_core] #![no_main] #[macro_use] extern crate cc65; use cc65::{cprintf, get_screen_size, goto_xy}; fn print_at_center<const N: usize>(line: u8, s: &[u8; N]) { let (width, _) = get_screen_size(); let padding = (width - N as u8) / 2; goto_xy(padding, line); cprintf!(b"%s\0", s); } #[start] fn start(_argc: isize, _argv: *const *const u8) -> isize { print_at_center(5, b"HELLO NES FROM RUST!\0"); print_at_center(15, b"ADVENT CALENDAR 2025\0"); print_at_center(20, b"STATIOLAKE\0"); loop {} } ããã ãé 匵ã£ãå²ã«ãC ãäžäŸ¿ã«ã©ããããã ãã§ãRust ã£ãœãããšã¯ã»ãšãã©ã§ããªãã®ã¯æ²ããããã«ãæããŸãããå®éã¯ã(èªåã§ã¯) Rust ã ããæžãã°ãã¡ãã³ã³ãåãããããã«ã§ããããšããåã³ã倧ããã§ãã ã¡ãªã¿ã« fizzbuzz ãåããŸããã¡ãã£ãšã¯ Rust ã£ãœãããã㪅ã #![feature(no_core)] #![no_core] #![no_main] #[macro_use] extern crate cc65; use cc65::{cprintf, get_screen_size, goto_xy}; fn fizz_buzz(n: u8) { let mut i = 1; while i <= n { goto_xy(0, i - 1); match (i % 3, i % 5) { (0, 0) => cprintf!(b"FizzBuzz\0"), (0, _) => cprintf!(b"Fizz\0"), (_, 0) => cprintf!(b"Buzz\0"), _ => cprintf!(b"%d\0", i), } i += 1; } } #[start] fn start(_argc: isize, _argv: *const *const u8) -> isize { let (_, height) = get_screen_size(); fizz_buzz(height); loop {} } ãªãã§ for i in 1..=n ãããªãã®ããã§ããïŒcore ã« Iterator ãå®è£
ããªãã£ãããã§ãâŠã cprintf! ãã¯ãããã©ãŒãããæå®ãèªåãªã®ã¯çæèœã¡ã§ããã format_args! ããµããŒãããã®ã¯ã³ãŒãé·çã«çžåœå€§å€ããã ã£ãã®ã§èŠéããŸããã ãšã¯ãããã®èŸºããé 匵ãã°å¿
èŠã«å¿ããŠå®è£
ããããšãå¯èœã ãšæããŸãã é·ãã£ãã§ããããããŸã§ãªããšããã©ãçããŸããã ãä»ãåãããã ãããããšãããããŸããã ãããã« çžåœé£ããéã³ã§ããããèªåãæã€æè¡ã»ããã§èããã°äžçªæ¥œããã«ãŒããéžã¹ããšãæããŸããæåã¯ããããªããšèªåã§ãæã£ãŠããã®ã§ãããååã«åŠã³ã®ããã«ãŒãã§ããã ç®è«èŠéããC èšèªãäžéèšèªãšããŠæãã ããšã§ãäœãèµ·ããŠãããããããããããèªåã§ããããç¯å²ã倧ããã£ãã®ãè¯ãã£ãã§ãã ãã®æ¹éã§å€§ããªãã®ãäœãã®ã¯é£ããã§ãããããããã¡ãã£ãšãããã¯äœã蟌ãããã§ã¯ãããŸããæããã«ãªãŒããŒãããã¯å€§ããã®ã§ãã«ãã«åãããªã¥ãŒããŒãªã²ãŒã ã¯äœããªããšæããŸããããªã¢ã«ã¿ã€ã æ§ãäœããªãããããè¿·è·¯ã¿ãããªãã®ãªãã§ããŠãè¯ãããã ãªãšããããææŠãããããããŸããã ãŸãä»åãcore crate ã®ãµãã»ãããåå®è£
ããããšã§ Rust ã§åœããåã«ã§ããŠããããšãã©ã®ãããªä»çµã¿ã§è§£æ±ºãããŠããã®ãã®äžç«¯ãäœæããŸãããããšãã° &str -> *const u8 ã®ãããªããªãã¡ã¬ã³ã¹ããã§ããŸããã Unsize ãšã CoerceUnsize ãšããããæ®æ®µãªãç®ã«ãããªããããªãã¬ã€ããå¿
èŠãªãã ããã§ããäž¡æäž¡è¶³ããããããããªããã°ã©ãã³ã°ã§ããããããã¯ããã§æ°é®®ã§é¢çœãã£ãã§ãã 40 幎以äžåã®ããŒããŠã§ã¢ãšçŸä»£ã®èšèªãç¡çããç¹ãããšããã誰åŸãªãã£ã¬ã³ãžã§ãããããããŸã§ãèªã¿ããã ãããããšãããããŸããïŒ ææ¥ã®èšäºã¯ãRust Advent Calendar ã¯ãŸã æªå®ã®ããã§ããããããã£ã°ã«ãŒã Advent Calendar 㯠@su6y ããã®ãAWS IAM Identity Centerçµç±ã§Kiroã䜿ã£ãŠã¿ããã§ãïŒã楜ãã¿ã«ã â»ããã¡ãã³ã³ãããã¡ããªãŒã³ã³ãã¥ãŒã¿ãã¯ä»»å€©å æ ªåŒäŒç€Ÿã®ç»é²åæšã§ãã â»æ¬èšäºã®å
容ã¯åäººã®æè¡æ€èšŒã«åºã¥ããã®ã§ãããä»»å€©å æ ªåŒäŒç€Ÿãšã¯äžåé¢ä¿ãããŸããã