京都府舞鶴市、東舞鶴の商店街の大門通り沿い、元舞鶴高専の先生で、PCN舞鶴代表の町田さんによる、プログラミングもできる電子工作&模型屋さん「舞鶴電脳工作室」オープン!(アクセス


こどもから大人まで、ワクワクするお店!店頭の模型や、電子工作見ていると、ちょっと覗いてみたくなりますね。


福井県大野市、元福井高専の先生、前川さんによるPCN大野研究所で採れたイチゴを直送!


電波の先生、前川さん。電波を見るツール「Nano VNA」が良い感じとのこと。 オープンソースな高周波解析機。日本語ユーザーガイドもオープンソースで作成されていました。 コロナ禍、飛行機に電波を当てて反射させての通信実験、旅客機は減っても、貨物は比較的飛んでいるとのこと。人には見えないものが見える力、広めましょう!


真っ赤になった、甘いイチゴ!いつの日かしたい、イチゴ収穫ロボコン。


舞鶴電脳工作室で仕入れた電子部品と大野さんイチゴのコラボ!IchigoJamでMAX7219マトリクスLEDチェーンの制御できました!


風通しの良い店内、ミニ四駆コースがこどもに人気とのこと!IchigoJamを使った計測システムも計画中とのこと!


抵抗、コンデンサ、LED、基本パーツが揃っていてうれしい、電子パーツコーナー。


15 マイコン、と書かれた電子工作用部品コーナーにはIchigoJamも。右下に見慣れない部品を発見!


8x8の赤色マトリクスLEDx4、全部に制御用のIC、MAX7219搭載でデイジーチェーン対応。これで400円は安い!

MAX7219制御のマトリクスLEDx4のIchigoJam制御チャレンジ!

MAX7219/MAX7221データシートをチェック、日本語ドキュメントがありますね。7セグLEDを8コまとめて制御するチップの様子。 4bitで数を指定すると7セグLED用にデコードするモードと、そのままストレートに8bit分出すモードがあります。8桁以上に対応するためにWS2812Bの用にデータを後ろにパスする仕組みがあります。 転送方式は16bitのSPI、FM音源チップYMF825などでやりました。

VCC 5V
GND GND
DIN シリアルデータ入力 - IchigoJamのOUT3
CS チップセレクト - IchigoJamのOUT1
CLK クロック - IchigoJamのOUT2

とIchigoJamと接続して、ひとまずBASICで実験!

500 @SPIW:OUT1,0:FORI=15TO0STEP-1:OUT2,0:OUT3,N>>I&1:OUT2,1:NEXT:OUT1,1:RTN N=12<<8|1:GSB@SPIW

付きました!(SHUTDOWNアドレス12のbit0に1で表示)

SPIはBASICのままだとゆっくりなので、マシン語化して高速化。ライブラリとして整えて、サンプルプログラムと合わせてできあがり!

10 GSB@INIT 20 N=5:GSB@INTENSITY 30 S="0528":GSB@SHOW:WAIT30 40 S=" jig.jg ":FORK=0TO10:GSB@SHOW:WAIT10:S=S+1:NEXT 60 S="17th":GSB@SHOW 70 FORJ=0TO7:N=J&1*9+5:GSB@INTENSITY:WAIT10:NEXT:WAIT30 80 GOTO 20 200 @INIT 210 POKE#700,80,35,27,2,91,28,27,4,1,33,201,3,0,34,8,66,0,208,4,50,154,97,2,50,154,97,73,8,246,209,112,71 220 N=7:GSB@SCANLIMIT:N=1:GSB@DISPLAY:RTN 300 @SHOW:FORJ=0TO7:OUT1,0:A=(J+1)<<8:FORI=0TO3:C=ASC(S+I):N=PEEK(C*8+J):U=USR(#700,A|N):NEXT:OUT1,1:NEXT:RTN 400 @INTENSITY:N=10<<8|N&#F:GSB@CMD:RTN 410 @DISPLAY:N=12<<8|N&1:GSB@CMD:RTN 420 @SCANLIMIT:N=11<<8|N:GSB@CMD:RTN 500 @CMD:OUT1,0:FORI=0TO3:U=USR(#700,N):NEXT:OUT1,1:RTN

300 @SHOW S:display chars 4桁表示 (I,J,A,C,N,Uが破壊される)
400 @INTENSITY N=0-15 輝度設定 (I,Uが破壊される)
410 @DISPLAY N=0/1 表示のON/OFF制御、最初にONにする (I,Uが破壊される)
420 @SCANLIMIT N=0-7 使用する最後の行、今回は7まで8行全部使う (I,Uが破壊される)
500 @CMD cmd send x4 - 16bitのコマンドを4つ分送信 (I,Uが破壊される)


後ろにどんどんつなげることができるので、もっと長くしたり、縦16ドットにしてみたり、高速化するためにループをマシン語化してみるなど、必要に応じて改造しましょう!

今回のプログラムの見どころ、4文字表示する処理300行@SHOWを丁寧に書くと、下記のような2重ループになっています。

300 @SHOW 310 FORJ=0TO7 320 OUT1,0:A=(J+1)<<8 330 FORI=0TO3 340 C=ASC(S+I):N=PEEK(C*8+J) 350 U=USR(#700,A|N) 360 NEXT 370 OUT1,1 380 NEXT 390 RTN

OUT1でCSを0に、4つ分のデータをSPI転送して、CSを1にすることでバケツリレー!

@SPIWのマシン語バージョンはこちら。asm15でアセンブルしてみましょう。

' @SPIW:FORI=15TO0STEP-1:OUT2,0:OUT3,N>>I&1:OUT2,1:NEXT:RTN @SPIW R3=#50 ' R3=#50010000 R3=R3<<8 R3=R3+1 R3=R3<<16 R1=1 R1=R1<<15 @LOOP R2=0 R0&R1 'F=N>>(15-I)&1 IF 0 GOTO @SKIP R2+=4 ' for OUT3 @SKIP [R3+`110]L=R2 ' OUT2,0:OUT3,F R2+=2 ' for OUT2 [R3+`110]L=R2 ' OUT2,1 R1=R1>>1 IF !0 GOTO @LOOP @END RET

OUTポートを変更する場合は、適宜プログラム内の数を変更しましょう(マシン語入門


小学生の頃、敷居の高さにあきらめたプラモデルの塗装。


塗装コーナー、人気とのこと!


美しい、塗装された模型!VRで塗装体験できるもの作ってみるのも入門にいいかも!?

新しい世界への入口「舞鶴電脳工作室&PCN舞鶴」でした!

links
- 舞鶴電脳工作室に子供パソコンIchigoJamの開発者の福野さんがご来店 | Cyber Workshop in Maizuru

以前紹介した、5コ950円で買える、安価でIchigoJam BASICだけでも使える超音波センサー「HC-SR04」。 他デバイスとの関係で、どうしてもBTNを使いたいとご要望あり。


できました!IchigoSodaにつないでIoT化していますが、IchigoJam、IchigoDakeでもOKです!

BTNはIchigoJam付属のボタンとSLEEPからの復帰のため外部でプルアップ抵抗をつなげていて、ANA(0)としてアナログ入力としても使えます。 つまり、CPU内部の設定としてはアナログになっているので前回紹介したマシン語で読み出そうとしてもうまくいきません。


BTNを割り当てているPIO1_4、LPC1114のデータシートの IOCON_PIO1_4 (アドレス#40044094) を見ると設定方法が書いてあります。 一度、マシン語を使ってどういう設定になっているか読み出してみましょう。

R0=[@IOCON_PIO1_4]L R0=[R0]L RET @IOCON_PIO1_4 DATA L #40044094

asm15でアセンブルして、読みだした値を8桁の2進法で表示

POKE#700,1,72,0,104,112,71,0,0,148,64,4,64 OK ?BIN$(USR(#700,0),8) 01000001

2:0 つまり最下位の0bit目から2bit目の3bitを使ったFUNCは1、次の2bitのMODEは0(プルアップなどなし)、次の1bitのHYSは0(無効)、6bit目はReservedとして予約されていて1を設定することになっていて、7bit目ADMODEが0でアナログ入力モードとなっています。

これをADMODE:デジタル入力+FUNC:PIO1_4と、`11000000 に一時的に変更する作戦でいきます。前回のカウントプログラムの前後にこの設定を足します。

PIO1のベースアドレスは #50010000、BTNは、PIO1_4の場所なので
?"#5001";HEX$(1<<(4+2),4) → #50010040 を@INに設定します。

'BTN(PIO1_4) <- digital R1=`11000000 R3=[@IOCON_PIO1_4]L [R3]L=R1 'count check R0=0 R1=[@IN]L @LOOP R2=[R1]L R0=R0+1 R2-0 IF !0 GOTO @LOOP R0=R0>>9 'BTN(PIO1_4) <- analog R1=`01000001 [R3]L=R1 RET @IOCON_PIO1_4 DATA L #40044094 @IN DATA L #50010040 'BTN=PIO1_4

アセンブルして、BASICのプログラムと組み合わせて、できあがり!

10 POKE#700,192,33,6,75,25,96,0,32,5,73,10,104,64,28,0,42,251,209,64,10,65,33,25,96,112,71,0,0,148,64,4,64,64,0,1,80 20 OUT1,1:OUT1,0:?USR(#700,0) 30 WAIT 5:GOTO 20

マシン語でカウントした値、R0をBASICに返す前に9ビット右シフト、つまり512分の1にしています。マシン語のカウントだと速すぎて大きな値になってしまうからですが、ここをいじると精度アップが見込めます。 ただ、IchigoJamでは1秒間に1.5万回くらい画面表示用の割り込みが発生するので、高い精度で計測するには割り込みを一時的に止める必要があります。

CPSID R0=0 R1=[@IN]L @LOOP R2=[R1]L R0=R0+1 R2-0 IF !0 GOTO @LOOP R0=R0>>5 CPSIE RET @IN DATA L #50001000 'IN1=PIO0_10

割り込みの一時停止は CPSID、最下位は CPSIE です。戻し忘れると何も操作できなくなってしまいます。下記、CPSIDした後リターンする危険なプログラム、SAVEした後、お試しください。

LET[0],#B672,#4770:?USR(#800,0)

完成した、超音波センサー、TrigをIN1に接続し、精度16倍バージョンがこちら!

10 POKE#700,114,182,0,32,3,73,10,104,64,28,0,42,251,209,64,9,98,182,112,71,0,16,0,80 20 OUT1,1:OUT1,0:A=USR(#700,0):?A 25 LED A<300 30 WAIT 5:GOTO 20

一定距離から近づくとLEDがついてお知らせ、リレー経由でスゴイ照明と組み合わせると防犯ライトにもなりますね!

5 B=0 26 IF B=0 AND A<300 B=1:N=N+1:IOT.OUT N:?"IOT!";N:WAIT30 27 IF B=1 AND A>=300 B=0

IchigoSodaを使って通ったらIOT.OUTでカウントを送るように改造も簡単です!
福井県で始まった「混雑状況オープンデータ」との連携も便利そう。


Let's IoT with IchigoJam x various sensors!

links
- 200円 超音波距離センサー HC-SR04 を IchigoJam で使う方法 - Armマシン語で時間を測ろう
- 今週末は越前がにロボコン! IchigoJamで超音波センサーをIN1とは違うポートで使う方法 BASIC編 マシン語編

初心者にはオススメできないC言語ですが、多くの高専の授業で登場するC言語

#include <stdio.h> int main() { printf("Hello World!\n"); return 0; }

このC言語のプログラムを実行すると

Hello World!

と出ます。これで感激できるのはC言語を作った人と、環境構築に苦労した人くらい。大抵の人は「で?」と思うだけでしょう。 なぜ # で始まる? <stdio.h> はHTMLのタグとは違う? studio のつづり違い?など1行目から分からないことだらけです。

こちら、その謎に本質から迫るため開発した、x64版の超シンプルマシン語標準入出力ライブラリ stdio.asm を Windows 10で動かした様子。Mac/Linux/FreeBSDでも同様に動きます。

今日の記事はC言語を少しやったけど、なんだかスッキリしない人、現代PCの主力CPU、Intel/AMDのx86系x64マシン語を使ったOSの深い話が気になる人向けです。 まずは楽しくプログラミングでゲームを作ってみたい人や、マシン語の基本は、シンプル&コンパクトなパソコン、IchigoJamからスタートするのがオススメです。(IchigoJam入門動画はじめてのマシン語

C言語プログラミング、本当のはじめのいっぽはこちらです。

int main() { return 1 + 1; }

これを test1.c と保存し、コンパイルし、実行し、実行結果を表示すると(for macOS/Linux)

gcc test1.c ./a.out echo $? 2

1 + 1 という人間らしい言葉で、コンピューターに計算させることに成功!

細かく解説すると・・・。 こちら、整数(int)を返すmainと名付けた関数(数学の関数と似たもの)を作り、中身に「1 + 1」を返して(return)と記述したC言語のプログラムです。 mainという名前は特別で、プログラム起動時に最初に呼び出されます。 「1 + 1 」という人にわかりやすい言葉を、コンピューターが分かる言葉、マシン語へ変換してくれるのがC言語のコンパイラというツールです。 gccというコンパイラは、特に何も指定しないと a.out という実行ファイルができます。それを、実行。 プログラムが実行した結果をみるコマンド(echo $?)を使って、コンピューターが計算した結果「2」を得ることができた。というわけです。

ゲームのキャラクターを表示したい、コントローラー入力を使いたい、音を慣らしたい、いろいろ欲が出てきます。 そこで登場するのがライブラリ。コンピューターの仕様を隅から隅まで調べなくても、誰かが作ってくれた便利な部品を使うことで楽できます!

そんなライブラリの代表格が stdio.h(スタンダードI/Oの略) で定義されている標準ライブラリというものです。 基本的な文字の表示(output)と入力(input)のための関数が揃っています。 冒頭に登場した、printfという関数もそのひとつ。

int main() { printf("hello!\n"); return 0; }

上記のようにプログラムを変更してコンパイルすると、printfって何?とエラーになります。

printfを事前に定義する必要があります。stdio.h というファイルに定義があります。#include は指定したファイルを埋め込んでくれます。 ファイル stdio.h はどこにあるのでしょう?コンパイラが含めるために使うディレクトリが決まっていてその中のを使ってというのが、「<」と「>」で囲う意味でした。 その場にある自分で作ったファイルを含めるときは、ダブルクォートで囲みます。 HTML,CSS,BASIC,C,JavaScript,Pythonなど、コンピューター言語毎に、記号の意味は変わります。

文字の表示やサウンド出力などの手順は、Windows/macOS/LinuxなどのOS毎に違います。 C言語のコンパイラはCPUの違いを吸収してマシン語を生成してくれますが、手順の違いを吸収するのはライブラリの役目。

例えば、Macで文字を出力するには、レジスタrsiに出力したい文字列の先頭アドレスを、レジスタrdxに長さを、rdiに1を、raxに0x2000004をそれぞれ設定して、システムコール(syscall)を呼ぶことで、OSが文字を表示してくれます。(stdio_mac64.asm src on GitHub、cmd: nasm -f macho64 hello.asm -DMAC64; ld -lSystem hello.o -o hello )

mov rdi, 1 ; fd = stdout mov rax, 0x2000004 ; syscall write syscall

CentOS, Ubuntu, Debian, OpenSuSE, Arch Lniux, Fedoraなど、多くのLinuxではレジスタraxに設定するシステムコール番号を変えるだけでOKです。(stdio_linux64.asm src on GitHub、cmd: nasm -f elf64 hello.asm -DLINUX64; ld -e _main hello.o -o hello )

mov rdi, 1 ; fd = stdout mov rax, 1 ; syscall write syscall

FreeBSDでは他のLinuxと異なります。macOSはBSD系の子孫、この値に 0x2000000 数を足したものです。(stdio_bsd64.asm src on GitHub、cmd: nasm -f elf64 hello.asm -DBSD64; ld -m elf_x86_64_fbsd -e _main hello.o -o hello )

mov rdi, 1 ; fd = stdout mov rax, 4 ; syscall write syscall

Windowsでは直接システムコールを呼んではいけないことになっていて、dll(ダイナミックリンクライブラリ)を経由しての呼び出しとなります。stdio_stdout の初期化が必要で、レジスタの使い方や、スタックの使い方も違います。(stdio_win64.asm src on GitHub、cmd: nasm.exe -fwin64 hello.asm -DWIN64& link.exe /entry:_main /subsystem:console hello.obj kernel32.lib )

mov r8, rdx ; len mov rdx, rsi ; buffer mov rcx, [rel stdio_stdout] mov r9, stdio_bytesWritten push qword 0 call WriteFile

このようにOSによってそれぞれ使い方は異なりますが、名前と使い方に揃えれば、以後気にしなくてよくなります。stdio.asm で、環境によって使うライブラリを切り替えるようにしておきます。

%ifdef WIN64 %include "stdio_win64.asm" %elifdef MAC64 %include "stdio_mac64.asm" %elifdef LINUX64 %include "stdio_linux64.asm" %elifdef BSD64 %include "stdio_bsd64.asm" %endif

こうして準備をしておき、stdio.asm を include すれば、どのOSでも動くマシン語でプログラム「Hello World!」が、このようにシンプルに書けます。NASMでのファイルへの埋め込みのincludeは#ではなく%。 いろんな環境での動作確認はConoHaのVPSを使うと1環境1時間1円〜と、とても手軽です。

%include "stdio.asm" global _main section .rodata MESSAGE db "Hello World!", 0x0d, 0x0a LEN_MESSAGE equ $-MESSAGE section .text _main: call stdio_init mov rsi, MESSAGE mov rdx, LEN_MESSAGE call stdio_write mov rdi, 0 call stdio_exit ret

開発効率、速度、汎用性の向上や、特殊な用途への特化するためなど、さまざまなプログラミング言語が誕生し、使われたり、廃れたりしていますが、結局動いているのはこれらマシン語です。 基本を抑えておけば、余計な手間をかけることなく、楽しく楽に開発できてますますプログラミングが楽しくなります。

理解を深めるには、実際にやってみるのが一番です!Windows/Mac/Linux/FreeBSD、それぞれ環境に合わせた c-*.sh/bat、c-*-test.sh/bat を使って、実際に動かしてみましょう。(src on GitHub

開発に必要なツールを設定しましょう。Windowsでは「Visual Studio C++ 2019 コミュニティ」、Macでは「Xcode」がそれぞれ無料で提供されています。 アセンブリ言語をマシン語化してくれるツール、アセンブラ「NASM」もオープンソース、無料です。

Visual Studio C++ 2019 コミュニティ、右側赤枠で囲んだ2つ、ビルドツールとSDKがあれば、ひとまず今回の開発は可能です。セットアップ後、コマンドプロンプトで hello-x64asm のディレクトへ移動し init-win.bat を動かし、開発ツールとNASMにPATHを通して、レッツトライ!

stdio.asm は、stdio.h が持つ機能の極一部。自分なりのライブラリや、プログラミング言語づくりにチャレンジするのもおもしろいですよ!

links
- taisukef/hello-x64asm: the first step of x64 64bit assembly programming on Windows/macOS/Linux
- C言語開発者「C言語は初心者にはお勧めできない」 エントリーにオススメBASICは、世界初のクラウド対応言語だった! IoTで起業家甲子園目指す、長岡高専チームメンタリング
- プログラミング言語は何から学ぶべきか? ロボットプログラミングゲームをIchigoJamでプログラミング! C言語の教科書「Springs of C」より
- 高専でなぜC言語を学ぶのか? IchigoJamマシン語生成プログラム c4ij で作る、C言語版かわくだり
- IchigoJamからのステップアップ - IchigoJam BASIC / Python3 / JavaScript / Java / C言語 対照表
- ハンドアセンブルで高速計算! RISC-V、RV32ICエミュレーターのC言語実装
- マシン語対応 IchigoJam web、気軽にハンドアセンブルして遊べます!
- OpenCL/C言語 GPUプログラミングはじめのいっぽ on Mac
- わずか16KB! WebAssemblyで動くミニC言語オフラインコンパイラ&インタプリタ webci0
- 深いプログラミング言語学習に最適! 512行のC言語コンパイラ ci0 を使ってみました
- 地味なC言語がなぜ楽しいのか?

長らく使ってきた macOS Mojave から Catalina へ移行。32bit開発のためにと残して来たがRISC-Vの開発環境が非対応となり決心。 記念に動かなくなってしまう 32bit版bootBASIC を、64bit化。


「bootBASIC_64bit for MacOS」(src on GitHub)
nasmでアセンブル可能。 コンパクトな実装でプログラミング言語づくりの入門にぴったり。 WindowsやLinuxへの移植もチャレンジしたいが、やってみたい方、fork/プルリク、大歓迎! 512byteのブートセクターに収まる「bootBASIC」を開発した、nanochessさん、ありがとう!(Thank you! nanochess-san.)

10 A=1 10 A=1 20 A=A*10 30 PRINT A 40 GOTO 20 >RUN 10 100 1000 10000 100000 1000000 10000000 100000000 1000000000 10000000000 100000000000 1000000000000 10000000000000 100000000000000 1000000000000000 10000000000000000 100000000000000000 1000000000000000000 -8446744073709551616

16bitのAXレジスタは、32bitでEAX、64bitでRAXへと段階的に進化を遂げたx86マシン語。今回変数も64bit化。100京まで表示!

; Compare statement (rsi, rdi, length:rcx) ; case sensitive check (original) ; rep cmpsb ; jne statement_not_match ; Equal? No, jump ; case insensitive check statement_check: mov al, [rdi] and al, 0xdf mov ah, [rsi] and ah, 0xdf cmp al, ah jne statement_not_match inc rdi inc rsi dec rcx jnz statement_check statement_check_end:

やっぱり、BASICなので、大文字表記にも対応したい。rep cmpsb という、ループ付きマシン語命令を大文字小文字を区別しないループに変更。

慣れない言語であってもネット時代、探せばすぐに解決する良い時代。x86マシン語に関して「Jun's Homepage」が参考になりました。 32bitのEAXで代入するとRAXの上位32bitは0クリアされるとか、MULやDIVが暗黙的にRDXが使われるとか、ハマりやすいポイントが分かります。

このサイト作者によるコンパクトなプログラミング言語「Return of Very Tiny Language」を発見!

IchigoJam BASICの元になったTinyBASICより、更にコンパクトなプログラミング言語VTLの64bit版!ファイルや画像も扱えるように大幅パワーアップ!(VTL系言語の歴史

Linux版をmacOSで動くように少しだけ書き換えて、コンソールでシンプルのVTLを体験することができました。
taisukef/rvtl-amd64: RVTL : Tiny BASIC in x86_64 assembly language for macOS (開発途中)

移植で困ったのは、アセンブル時にでるエラー「error: 32-bit absolute addressing is not supported in 64-bit mode」。アドレスに @GOTPCREL(%rip) をつけて回避とありましたが、Intel表記では使えず、ひとまず使ってなさそうなr15レジスタを介する形に修正。

macOS Catalina 化もトラブルなく終了。Windows NT 3.51 (1996年)から続いた32bit開発環境に分かれを告げました(クロス開発は除く)。 当時の開発環境は、Intel Pentium 90MHz、RAM16MB、HDD1GB、VC++。何より技術資料へのアクセス手段が紙頼み。良い時代になりました。

速いプログラムを作る基本は、ループ数を減らすこと、ループ内を軽くすること。

100円のCPUでも1秒間5,000万回計算してくれますが、4K動画に必要な2500万コのLED制御、1コ1計算だとしても1秒間に2コマの紙芝居にしかなりません。 滑らかで美しい映像を計算するためには高速化が欠かせません。

計算で作る美しい映像例「ライフゲーム」、IchigoJamでも「Kubotaさんのライフゲーム - IchigoJam-FAN」にて、高速化チャレンジ中。 100円CPU、Arm Cortex-M0では、足し算、引き算、掛け算と比較して、割り算が150倍遅いことを「IchigoJamマシン語入門」で確認しました。では、普通のPCではどうでしょうか?

MacやWindowsは、Intel/AMDのx64アーキテクチャーが大半です。Intelの資料によると、レイテンシー(ざっくり実行してから結果がでるまでの時間)で、掛け算(MUL)は足し算(ADD)の10倍、割り算(DIV)は足し算の66倍〜80倍ほどかかることがわかります。
インテル ® 64 アーキテクチャーおよび IA-32 アーキテクチャー最適化リファレンス・マニュアル
プログラミング言語、コンパイラーを作る人には必見のこの資料、日本語でここまで用意されているのはスゴイ! ちなみに、ハードウェア除算命令がある Arm Cortex-M3 での掛け算は足し算と変わらず1クロック、除算はその2〜12倍です。(18.2. プロセッサ命令のタイミング - ARM Information Center

どんな環境でもループ内の割り算は少なくするのが得策です。ループ外にもって行けないか、ビットシフトや掛け算で代用できないか検討しましょう。32で割る整数計算は、2進数のビット演算で5bit右にシフトするのと一緒で、速度はどのアーキテクチャーでも1クロックになるのでとても有効です。

掛け算の使用はアーキテクチャーで判断が分かれます。IchigoJamやスマホなど、Armアーキテクチャーでは掛け算が足し算と同様に高速なので、カジュアルに使えますが、PC向けの場合多少命令が増えても、事前計算や、足し算ビット演算などでの代用が有効そう。

IchigoJamでのライフゲーム、1更新が16秒から14.5秒に短縮されたとのこと!Cortex-M0は、構造がシンプルなので速度計算が簡単で、遅い分、効果が体感で分かるのが楽しいです。

ループ内を軽くする手段の一つ、並列化。Intel/AMDのx64には512bitのSIMD命令、AVX-512という512bit(8bit x 32コ)まとめて計算する命令があります。 zmm0〜zmm31という512bitレジスタを使った計算ができるとのことでしたが、残念ながら今使っているMacBookProではちょっと古くて非対応。 AVX2の256bit(ymm0〜ymm15)で足し算(vpaddb = 1クロック)させてみました。(src for Mac on GitHub)

せっかくなら持てる力、フルパワー使いたいですね!もっと長いビット長が計算できるRISC-Vのベクトル拡張も楽しみです。

GPUやFPGAなど、高速化のための様々な技術、必要に応じて楽しく使っていきましょう!

links
- サイズを取るかスピードを取るか、割り算のアルゴリズムとマシン語実装 / IchigoJamではじめるArmマシン語その14
- ハンドアセンブルで高速計算! RISC-V、RV32ICエミュレーターのC言語実装
- MacのGPUでも700倍速! パスワード20文字時代の盾と矛 / さくらクラウドで分散探査する方法
- Macで開発、FPGAで作る4bit学習用CPU「GMC-4」 - Parallels x Ubuntu x Quartus x Verilog

プログラムが思ったように動かない時、メモリ内容をチェックするのは常套手段。サーバーなどで使われるlinuxではコアダンプというのが有名です。

メモリを読むためにはどう記録されている把握していること、そのマシンのマシン語の知識が必須です。ただ、メモリがギガの単位(10億)までいってしまうと、人の目だけでチェックするのは現実的ではなくなってくるので、支援ツールを使いこなすテクニックが必要になります。

その点、メモリがキロの単位(千)のIchigoJamや、ファミコンゲームなら、自力でなんとかできますし、支援ツールを自作するのも簡単です。 本質的にやっていることは変わらないので、ホワイトハッカー入門にもぴったり!

JavaScriptで作られたファミコンのエミュレーター JSNES にメモリのリアルタイムモニター機能をつけるため、GitHubからソースをfork(自分のプロジェクトとしてコピー)しました。(src of JSNES by @taisukef on GitHub)

サンプルとして入っていた、GGJ2018で作られた「InterglacticTransmissing」を動かしている様子。 CHROMの256キャラクターx2を表示し、1024byte x 4 のVRAMも色付きで表示します。


[audio on]ボタンを押すと、サウンド出力にも対応。


[change rom]ボタンで、「Kawakudari for NES」に切り替えできます!
こちらはBGは不使用。スプライトを使っている様子が右下の囲み内で確認できます(主人公ネコは一番下、SPR63)

JSNESをforkして改良したポイントは、import/export対応。Node.jsで使われているJavaScriptのファイル単位のインポートの仕組み require を書き換えて、web上でも分かりやすくモジュールに別れたプログラムそのままで、動くようにしました。

nes-embed.js - ブラウザ組み込み用サンプル(自由に改造しよう!)
nes.js - ファミコンエミュレーター
conroller.js - コントローラー
cpu.js - MOS6502 CPU
rom.js - プログラムやキャラクターROM
mappers.js - メモリマップドI/O
ppu.js - グラフィックチップエミュレーター
tile.js - BG
papu.js - サウンドチップエミュレーター
utils.js - 便利メソッド集

どれもシンプルでキレイな実装です!
ハードウェアとソフトウェアをつなぐ鍵、マシン語。楽しく遊びながら学びましょう!

ボストンクラブのメガネ「JAPONISM JN-590 COL.01」、neoplug+ウェアラブル、主人公を助けるスゴイ電脳メガネが登場した、映画「AI崩壊」。 主人公が扱うプログラミング言語は Intel x86マシン語 でした!(他にもPythonや、PythonとC言語が混ざった感じの謎のプログラミング言語が登場)
31byteのマシン語で詠む和歌!? アセンブラ短歌 WakaAssembly for macOS 32bit編

映画を見て、情報セキュリティに関して興味が出てきた方にオススメしたいイベント
サイバーセキュリティフォーラム&ミートアップin 福井」(2020.3.2)
知識を日々アップデート!

links
- かわくだりゲーム for NES、はじめてのファミコンゲームづくり
- はじめてのマシン語 - IchigoJamではじめるArmマシン語その1

テレビの世界を自在に操れることに衝撃を受けたファミコン。そのファミコンのゲームをつくりたくて買ってもらおうとしたファミリーベーシック。母親が買ってきたのは、MSX。

今こそ作ってみよう、ファミコンゲーム! 分かりやすい入門記事を発見「suzukiplan/mgp-fc: ファミコンで始める ~ 6502マシン語ゲームプログラミング」。 GitHubに公開された、サンプルゲーム「COSMIC SHOOTER」「Battle Marine」もステキ! MOS6502のマシン語は「モジュール 6502」を参照。


「Kawakudari for NES」src for NESASM on GitHub
画面、操作、音、ゲームの基本的なところをまず試すために「かわくだりゲーム for IchigoJam」をファミコンへ移植! RAM容量は、IchigoJamと同じ4KB(RAM2KB、VRAM2KB)、52色カラーの背景とスプライトを絶妙に使った省メモリ設計が見事!(参考、ファミコンのグラフィックスの省メモリ化テクニックとは? | POSTD
*NES = Nintendo Entertainment System (ファミコンの英語名)


JavaScriptで作られたファミコンエミュレーター、JSNESでも、サクッと動く。(nesファイルをダウンロードして、ドロップすればOK!)

sprite_put: lda #30 ; Y sta SP_CAT + 0 lda #236 ; cat sta SP_CAT + 1 lda #0; T sta SP_CAT + 2 lda #120 ; X sta SP_CAT + 3 rts

マシン語プログラムの一部、ネコ表示(IchigoJam的にかくと LC 120,30:?CHR$(236))。ファミコン、MSX、PanCakeにはあるけど、IchigoJamにはないスプライト。4byte使って座標とキャラクター番号、左右上下反転、パレットを設定すれば表示される。 6502のコンパクトな8bitマシン語が心地よい。


細かい挙動が気になったら、ソースコードで確認もでき、あれこれデバッグするためのツールを作ったりも、自由に自在なオープンソース!(src on GitHub


手軽にファミコンカセットにする方法、模索中。

links
- suzukiplan/mgp-fc: ファミコンで始める ~ 6502マシン語ゲームプログラミング
- はじめてのマシン語 - IchigoJamではじめるArmマシン語その1(上記が難しかったらこちらや BASIC から遊びましょう)
- 高橋名人緊急参戦! 高専や技術の先生向け、トラ技ジュニア読者限定セミナー 直伝プログラミング実習(ファミリーベーシック入門の著書!)

マシン語や、アセンブリ言語、高専で習いましたか?

コンピューターはマシン語で動く機械。家電が電機で動くくらいの基本です。
全小学生がプログラミングする時代、さらっと15分でマシン語の肝、押さえましょう。

前提知識は、鯖江市の小学4年生向け総合2コマでも実施しているプログラミング体験。
大きな文字が大人に優しい、はじめてのプログラミング with IchigoJam スライド資料3種のオープンデータ! KDDI連携、福井県小浜市編
まだの方は IchigoJam または IchigoJam web と上記スライドを使って、まずはさらっとご体験ください!

IchigoJam BASICを使った、1から100までの地道な足し算。

A=0:FOR I=1 TO 100:A=A+I:NEXT:?A 5050

AやIは変数と呼ぶ、コンピューター内の記憶です。Aはひとまず0と覚えてもらいましょう。 リファレンスを見ると、FORとNEXTコマンドでIが1から100まで繰り返すことがわかり、変数Aがどんどん書き換えられて、最終的に?(=PRINT)で、表示するプログラムと読めると思います。(A=A+1 は LET A,A+1 の省略形)

コンピューターは数の計算しかできません。上記のプログラムもすべて数として処理されています。IchigoJam BASICというOSは、かかれたプログラムを1文字ずつ文字コードを照合しながら、知っている言葉を見つけたら、その処理を行うことを繰り返します。知らない言葉に遭遇したら「Syntax error」と返すのもOSの役目です。

一文字ずつ、丁寧に処理しているので、真の力は発揮できていません。
そこでマシン語の登場です!

?USR(#800,100) Segmentation Fault

指定したメモリをマシン語として解釈して、動かすコマンドUSR(ユーザー)を使うと、エラーになります。(IchigoJam 1.4未満だと固まるので、電源入れ直しましょう)

IchigoJamで使っているNXP社のCPU LPC1114は、Arm Cortex-M0アーキテクチャーなので 0-65535(16bit)の数(=マシン語)によって動作を指定します。
BASICと同じように、繰り返し足し算するプログラムをマシン語でいれてみます。

LET[0],#2100,#1841,#3801,#D1FC,#4608,#4770 ?USR(#800,100) 5050

LETコマンドは配列に連続した値をセットしていきます。HELPコマンドで確認できますが、IchigoJamの配列はコンピューター内のメモリ#800(16進法で800という位置)に記憶された数の並びです。

マシン語を解読してみましょう! Armマシン語の仕様は2進法で区切ると読みやすいので、BIN$コマンドを使います。

?BIN$([0],16) 0010000100000000

マシン語表をみて、0と1の並びが一致するものを探しましょう。 早速、一番最初の Rd=u8 が、一致しますね。Rdの部分、6〜8番目が0なので、2進法で001、つまりR1、その後8bitが全部0、つまり R1=0 と解読できます。(R0〜R15は、CPUがもっている記憶領域、レジスタと呼びます)

同じように、6つのマシン語を解読していきましょう。

FORI=0TO5:?HEX$([I],4),BIN$([I],16):NEXT 2100 0010000100000000 1841 0001100001000001 3801 0011100000000001 D1FC 1101000111111100 4608 0100011000001000 4770 0100011101110000

解読すると、下記のような動作をしていることがわかります。

R1=0 R1=R1+R0 R0=R0-1 IF !0 GOTO -2 R0=R1 RET

IF !0 GOTO n8 は、ちょっとややこしいです。11010001の並びでまずマシン語がわかります。n8とは、2進法で8bit(8桁)使った飛び先を指定しますが、一番上の桁が1になっているものはマイナスの数を表します。全部8桁、全部が1だと-1、最後が0だと-2・・・と続く、2の補数表現を使います。 -4だとわかりますが、実はこれに2を足した場所 -2 が飛び先となります。R0を1減らして、0でなければ2つ前のマシン語、R1=R1+R0 のマシン語へ飛びます。

RETでBASICに戻ってくるときの R0 の値が、USRコマンドの値となって、表示されます。

CPU、Arm Cortex-M0 アーキテクチャーのLPC1114の最大動作周波数は50MHz、IchigoJam標準の設定では48MHzで動かしています。 1Hzは、1秒間に1回という単位、M(メガ)は、100万の意味。ほとんどのマシン語を1つ1クロックで処理するので、秒間最大5000万回で計算できるというわけです!

ループさせずにRETで戻らせてみたり、引き算、掛け算など、いろいろいじって思い通りになったり、ならなかったり、遊んでみましょう!

命令をいろいろ組み合わせれば何でもできそうな感が伝わりましたか? このマシン語をいい感じに生成するプログラムのことをコンパイラやランタイムと呼び、C言語をはじめ、いろいろな言語が動いている裏っ側となります。
(参考、C言語開発者「C言語は初心者にはお勧めできない」 エントリーにオススメBASICは、世界初のクラウド対応言語だった!

スマホで使われているのは 64bit化された Arm Cortex-Aシリーズ、PCでは Intel/AMD、これから活躍楽しみな RISC-Vなど、CPUによってマシン語の違いはありますが、基本は同じです。

もうちょっとマシン語遊んでみたい人は、こちら「はじめてのマシン語」をどうぞ!
マシン語も分かったし、いろいろ作ってみたい人にオススメは、JavaScript。サーバーからスマホ、PC、ゲーム機まで動くプラットフォーム数、最高です!

プログラミング好きな高専生、鯖江の自然豊かな古民家でのインターン、来てみませんか?

高専生なら気になる、徳島県神山町。
日本で4つめ、2023年に開校予定の私立「神山まるごと高専」ができる町!

CoderDojo神山と一緒にイベント「はじめてのプログラミング with IchigoJam」
山と川と光ファイバーのまち、神山町。自然もコンピューターも仲間にしちゃおう!

たっぷり2時間、楽しんでくれました!未来の高専生!?


今回の使用機材は学校などでの多人数一斉体験にオススメ「IchigoDyhook
お習字のように、最初はゆっくりタイピング、だんだん慣れてきたら、自分なりに改造してオリジナルゲームにして遊んだり、遊んでもらったり! 作ったり、使ってもらったりするこの楽しさ、病みつきになって早34年。飽きる兆候がありません。


はじめてのプログラミング with IchigoJam (IchigoDyhook)
標準、USキーボード、大きな文字版もあります(slide pptx/keynote/pdf on GitHub

加えて、情報系の高専の授業で登場する、一歩先行くマシン語体験
「コンピューターの真の速さを見てみよう!」

1から100まで地道に足していく計算、みなさんは何秒でできますか?

A=0:FOR I=1 TO 100:A=A+I:NEXT:?A

さすが IchigoJam、なかなかの速さで計算しますね。

でも、まってください。IchigoJamのCPU、1秒間に5000万回だったはず?
そうです、BASICという言語は自転車の補助輪のようにやさしく丁寧にまちがいがあったら教えるために、実はこれでもゆっくり動いています。

ちょっと背伸びして、コンピューターが分かる言葉「マシン語」を使ってみましょう。大丈夫、こちらを間違えないよう、ただ打つだけでOKです。

LET[0],#2100,#1841,#3801,#D1FC,#4608,#4770:?USR(#800,100)

でてくる答は同じですが、速さが全然違いますね!これが100円くんの真の力です。
興味が出てきた人は、こちら「はじめてのマシン語」をどうぞ!


会場はステキコワーキングスペース「神山バレー・サテライトオフィス・コンプレックス


Fabスペースもあり!高校生がいろいろ作っているとのこと! お互いのレーザーカッターや3Dプリンター用のデータを交換したり、Hana道場とのコラボできたらおもしろそう。


こちらが噂の「神山まるごと高専」の校舎候補、大きい!部室でも何でも遊び放題!?


鮎喰川(あくいがわ)を挟んだ向かい岸に寮が並ぶ予定とのこと


山の中に秘密基地!?なんと手作りのサウナ!杉の木を切り開き、木材や薪にするリアルマイクラな世界!灰は撒いて新たな木への栄養にする循環型な遊び場。


SHIZQ | 神山しずくプロジェクト
神山町内、移住組に寄るステキなお店がたくさん!ご案内いただいたグリーンバレー大南さん、キネトスコープ廣瀬と!


アメリカからの移住者によるブッガカフェ!おじいちゃんスペシャルという、ベトナムコーヒー風をいただく。


近くでは集合住宅新築中!人が集まる熱い町!

自然と人とコンピューターにがっつり触れ合うのが21世紀流の学び=遊び。
高専生のみなさん、鯖江の自然豊かな古民家でのインターン来てみませんか?
(現在、3/15-19、主に高専4年生向け春インターン募集中)

links
- IchigoJamとBASICで遊ぶプログラミングワークショップ|CoderDojo神山|note
- 神山まるごと高専設立準備委員会 on Strikingly

かわいく思えるようになったx86マシン語、深みにハマって行き着いた「アセンブラ短歌
57577の5行、31byteで動くマシン語で、2byte以上の命令が行をまたいではいけないというストイックなルールが良い!

一句詠んでみました。

68 57 61 6B 61 31 C0 68 6D 62 6C 79 68 41 73 73 65 89 E1 6A 0C 51 6A 01 50 B0 04 CD 80 EB E1

タイトル「WakaAssembly...」 (x86/macOS Mojabe 32bit)

コンピューターの凄さを一番すぐに感じられるのは、繰り返し。 人間では不可能な速さで正確無比に繰り返される様を見せつけ、それが自分の指示によるものだと体感したものを虜にしてしまう。 (参考、IchigoJam BASIC のプログラム、RUN on IchigoJam web by WebAssembly

10 PRINT "WakaAssembly"; 20 GOTO 10

アセンブラ和歌アセンブラ和歌と繰り返しから誕生した、WakaAssembly、WebAssemblyっぽくて輸出しやすいかも。

CatalinaにOSアップデートで動作しなくなってしまう、macOS最後の32bitアプリの記念に。

x86マシン語(アセンブリ言語)で書かれたソースはこちら

00000000 <_main>: 0: 68 57 61 6b 61 push 0x796c626d 5: 31 c0 xor eax, eax ; eax = 0 7: 68 6d 62 6c 79 push 0x65737341 c: 68 41 73 73 65 push 0x616b6157 11: 89 e1 mov ecx, esp 13: 6a 0c push 12 ; length 15: 51 push ecx ; buffer 16: 6a 01 push 1 ; stdout 18: 50 push eax ; dummy 19: b0 04 mov al, 4 ; sys_write 1b: cd 80 int 0x80 ; syscall 1d: eb e1 jmp _main

pushで一度に4文字分、直接詰めるのがさすがCISC!jmp _mainで先頭へジャンプし、繰り返すたびにスタックを積み続けるので Segmentation faul を出してちゃんと止まり、現代OSのありがたみを感じる。(bits 32 として、32bitモードでのアセンブルが必要)

行儀よく、スタック位置を合わせ ret で 0 を返して終わるバージョン main-1shot.s、31byteのバイナリを和歌表示するために作ったミニプログラム wakaout.c もあります。
詳しくは「x86asm/wakaasm src on GitHub」で!

links
- アセンブラ短歌 - 坂井弘亮 / slideshare
- 「オープンソース」を使ってみよう (第33回 アセンブラ短歌)
- 31バイトでつくるアセンブラプログラミング ~アセンブラ短歌の世界~ Kindle版
- 「57577」の機械語を詠む「アセンブラ短歌本」まとめ - Togetter
- 根っこは同じ! Z80経験者によるx86マシン語はじめ、512byte bootBASIC をmacOS用に移植

Tweet
クリエイティブ・コモンズ・ライセンス
この作品は「Creative Commons — CC BY 4.0」の下に提供されています。
CC BY / @taisukef / アイコン画像 / プロフィール画像 / RSS