いものやま。

雑多な知識の寄せ集め

『OS自作入門』を読んでみた。(その2)

前回はVimバイナリエディタとして使って直接フロッピーディスクのイメージを作った。

今回はアセンブラを使ってフロッピーディスクのイメージを作ってみる。

Binutilsのインストール

本ではNASMに似たnaskという著者作のアセンブラを使ってるけど、やっぱりアセンブラでよく知られているのは、GNUアセンブラ(gas)。
ということで、自分はnaskではなくgasを使ってみた。

gasはBinutilsというツール群に含まれている。
そこで、Binutilsをインストール。

Binutils - GNU Project - Free Software Foundation

インストールは簡単で、tarボールを落としてきて展開したら、configureスクリプトを実行してmakeするだけ。

$ tar zxvf binutils-2.28.tar.gz
$ cd binutils-2.28
$ ./configure --program-prefix=i386-elf- --target=i386-elf --disable-nls
$ make
$ sudo make install

configureスクリプト--program-prefixオプションをつけると、各ツールの頭に指定したプレフィクスがつく。
今回はi386-elf用のアセンブラその他を作るので、i386-elf-というプレフィクスをつけている。
(そうしないと、他のアーキテクチャ向けのアセンブラを作ったときに、名前がぶつかる)

また、--targetオプションで対象のアーキテクチャを指定している。

あと、--disable-nlsというオプションをつけているけど、これはNative Language Supportを無効にするもの。
このオプションをつけなかった場合、libintl.hが見つからないというエラーが出たので、つけている。
(このヘッダファイルはMacでQEMUのビルドをしてみた。 - いものやま。に書いたgettextの提供するヘッダファイルなので、同じようにインクルードパスを通してやるのでもOKのはず)

何はともあれ、これでBintuilsのインストールは完了。
i386-elf向けのアセンブラi386-elf-asというコマンドでインストールされている。

アセンブラソースの作成

Binutilsもインストールできたので、次はアセンブラソースの作成。
といっても、アセンブラでコードを書くのではなく、バイナリエディタと同じように、データを直接作ってみる。

gasの場合、.byte.intといった擬似命令(ディレクティブ)を使うことで、バイナリデータを直接書くことが出来る。
また、.skipという擬似命令を使うと、指定したサイズだけ隙間を作ることが出来る。

それらを使って書いたコードが、以下:

    .byte 0xeb, 0x4e, 0x90, 0x48, 0x45, 0x4c, 0x4c, 0x4f
    .byte 0x49, 0x50, 0x4c, 0x00, 0x02, 0x01, 0x01, 0x00
    .byte 0x02, 0xe0, 0x00, 0x40, 0x0b, 0xf0, 0x09, 0x00
    .byte 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
    .byte 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x29, 0xff
    .byte 0xff, 0xff, 0xff, 0x48, 0x45, 0x4c, 0x4c, 0x4f
    .byte 0x2d, 0x4f, 0x53, 0x20, 0x20, 0x20, 0x46, 0x41
    .byte 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00

    .skip 16, 0x00

    .byte 0xb8, 0x00, 0x00, 0x8e, 0xd0, 0xbc, 0x00, 0x7c
    .byte 0x8e, 0xd8, 0x8e, 0xc0, 0xbe, 0x74, 0x7c, 0x8a
    .byte 0x04, 0x83, 0xc6, 0x01, 0x3c, 0x00, 0x74, 0x09
    .byte 0xb4, 0x0e, 0xbb, 0x0f, 0x00, 0xcd, 0x10, 0xeb
    .byte 0xee, 0xf4, 0xeb, 0xfd, 0x0a, 0x0a, 0x68, 0x65
    .byte 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72
    .byte 0x6c, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00

    .skip 368, 0x00

    .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
    .byte 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00

    .skip 4600, 0x00

    .byte 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00

    .skip 1469432, 0x00

これをhello-os.sというファイルに保存すれば、ソースは完成。

asによるアセンブル

アセンブラソースが出来たので、これをasでアセンブルしてやる。

$ i386-elf-as -o hello-os.o hello-os.s

問題なくアセンブルが終われば、hello-os.oというオブジェクトファイルが生成される。

objcopyによるバイナリファイルの生成

ただ、これでフロッピーディスクのイメージが出来たかというと、そうではなく。

実際、生成されたhello-os.oの内容を表示してみると、以下のとおり:

$ hexdump -C hello-os.o |less
00000000  7f 45 4c 46 01 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  01 00 03 00 01 00 00 00  00 00 00 00 00 00 00 00  |................|
00000020  a4 80 16 00 00 00 00 00  34 00 00 00 00 00 28 00  |........4.....(.|
00000030  07 00 06 00 eb 4e 90 48  45 4c 4c 4f 49 50 4c 00  |.....N.HELLOIPL.|
00000040  02 01 01 00 02 e0 00 40  0b f0 09 00 12 00 02 00  |.......@........|
00000050  00 00 00 00 40 0b 00 00  00 00 29 ff ff ff ff 48  |....@.....)....H|
00000060  45 4c 4c 4f 2d 4f 53 20  20 20 46 41 54 31 32 20  |ELLO-OS   FAT12 |
00000070  20 20 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |  ..............|
00000080  00 00 00 00 b8 00 00 8e  d0 bc 00 7c 8e d8 8e c0  |...........|....|
00000090  be 74 7c 8a 04 83 c6 01  3c 00 74 09 b4 0e bb 0f  |.t|.....<.t.....|
000000a0  00 cd 10 eb ee f4 eb fd  0a 0a 68 65 6c 6c 6f 2c  |..........hello,|
000000b0  20 77 6f 72 6c 64 0a 00  00 00 00 00 00 00 00 00  | world..........|
000000c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000230  00 00 55 aa f0 ff ff 00  00 00 00 00 00 00 00 00  |..U.............|
00000240  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001430  00 00 00 00 f0 ff ff 00  00 00 00 00 00 00 00 00  |................|
00001440  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00168050  03 00 01 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00168060  03 00 02 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00168070  03 00 03 00 00 00 2e 73  79 6d 74 61 62 00 2e 73  |.......symtab..s|
00168080  74 72 74 61 62 00 2e 73  68 73 74 72 74 61 62 00  |trtab..shstrtab.|
00168090  2e 74 65 78 74 00 2e 64  61 74 61 00 2e 62 73 73  |.text..data..bss|
001680a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
001680c0  00 00 00 00 00 00 00 00  00 00 00 00 1b 00 00 00  |................|
001680d0  01 00 00 00 06 00 00 00  00 00 00 00 34 00 00 00  |............4...|
001680e0  00 80 16 00 00 00 00 00  00 00 00 00 01 00 00 00  |................|
001680f0  00 00 00 00 21 00 00 00  01 00 00 00 03 00 00 00  |....!...........|
00168100  00 00 00 00 34 80 16 00  00 00 00 00 00 00 00 00  |....4...........|
00168110  00 00 00 00 01 00 00 00  00 00 00 00 27 00 00 00  |............'...|
00168120  08 00 00 00 03 00 00 00  00 00 00 00 34 80 16 00  |............4...|
00168130  00 00 00 00 00 00 00 00  00 00 00 00 01 00 00 00  |................|
00168140  00 00 00 00 01 00 00 00  02 00 00 00 00 00 00 00  |................|
00168150  00 00 00 00 34 80 16 00  40 00 00 00 05 00 00 00  |....4...@.......|
00168160  04 00 00 00 04 00 00 00  10 00 00 00 09 00 00 00  |................|
00168170  03 00 00 00 00 00 00 00  00 00 00 00 74 80 16 00  |............t...|
00168180  01 00 00 00 00 00 00 00  00 00 00 00 01 00 00 00  |................|
00168190  00 00 00 00 11 00 00 00  03 00 00 00 00 00 00 00  |................|
001681a0  00 00 00 00 75 80 16 00  2c 00 00 00 00 00 00 00  |....u...,.......|
001681b0  00 00 00 00 01 00 00 00  00 00 00 00              |............|
001681bc

見てのとおり、アセンブラに書いた内容だけではなく、なんか余計なデータが追加されているのが分かると思う。

これは、オブジェクトファイルが生のバイナリデータではなく、ELF形式のデータになっているため。
どのメモリにロードすべきかや、シンボルの情報、デバッグ情報なんかが一緒に詰め込まれている。
(ちなみに、アセンブラに書いた内容は0x34から始まっている)

普通のプログラムであれば、OSがこれらの情報を読み取って、適切なアドレスにロードしてくれるんだけど、ここではそういったローダはいないので、生のバイナリデータの形に自前で展開してやらないといけない。

ただ、Binutilsにはobjcopyというバイナリファイルの形式を変換するツールが含まれているので、これを使うことでオブジェクトファイルを生のバイナリデータに変換することが出来る。
(※もちろん、リンクされてすべてのシンボルが解決されていないとダメ)

以下のコマンドを実行:

$ i386-elf-objcopy -O binary hello-os.o hello-os.img

-Oが出力形式を決めるためのオプションで、ここでbinaryを指定すると、生のバイナリデータに変換されて出力がされる。

出来上がったイメージファイルの内容を見てみると、以下のとおり:

$ hexdump -C hello-os.img 
00000000  eb 4e 90 48 45 4c 4c 4f  49 50 4c 00 02 01 01 00  |.N.HELLOIPL.....|
00000010  02 e0 00 40 0b f0 09 00  12 00 02 00 00 00 00 00  |...@............|
00000020  40 0b 00 00 00 00 29 ff  ff ff ff 48 45 4c 4c 4f  |@.....)....HELLO|
00000030  2d 4f 53 20 20 20 46 41  54 31 32 20 20 20 00 00  |-OS   FAT12   ..|
00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000050  b8 00 00 8e d0 bc 00 7c  8e d8 8e c0 be 74 7c 8a  |.......|.....t|.|
00000060  04 83 c6 01 3c 00 74 09  b4 0e bb 0f 00 cd 10 eb  |....<.t.........|
00000070  ee f4 eb fd 0a 0a 68 65  6c 6c 6f 2c 20 77 6f 72  |......hello, wor|
00000080  6c 64 0a 00 00 00 00 00  00 00 00 00 00 00 00 00  |ld..............|
00000090  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
00000200  f0 ff ff 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000210  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001400  f0 ff ff 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00001410  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00168000

ちゃんと出来上がっているのが分かると思う。

Makefileの作成

これでとりあえずフロッピーディスクのイメージが出来たわけだけど、このコマンドを毎回打つのは面倒。
打ち間違いとかも怖いし。
(昔、ShellのTabによる補完でgcc -o hoge.c hoge.cを実行してしまって、せっかく書いたソースを空にしてしまったことがある・・・)

そこで、簡単なMakefileも用意してみた:

.PHONY: all clean do

all: hello-os.img

hello-os.img: hello-os.o
  i386-elf-objcopy -O binary $< $@

hello-os.o: hello-os.s
  i386-elf-as -o $@ $<

clean:
   -rm *.img *.o

do: hello-os.img
  qemu-system-i386 -fda $<

実行するコマンドの前にあるのは必ずタブでないといけないので、そこだけは注意。

これで、makeとすれば、イメージが作成されるし、make doとすれば、qemuが立ち上がって実行もされる。

今日はここまで!

『わかばちゃんと学ぶ Git使い方入門』を読んでみた。

ツイッターを見ていたら、社畜ちゃんで有名なビタワンさんの次のツイートが。

そういえば以前CodeIQ MAGAZINEで連載してたよなぁ、と。

https://codeiq.jp/magazine/category/git-ai/

知らぬ間に冊子になっていたとは。

これは読んでみたいと、自分も早速hontoで検索。
電子書籍にもなってたので、サクッとゲット出来た。
しかも、500円引きのクーポンがちょうど使えたので、1,600円くらいでw
ビタワンさんのように本屋に駆け込む必要もないし、すぐに読めるし、場所も取らないし、そのうえさらに安いとか、やはり電子書籍はいいねw

内容と感想

それはさておき、内容と読んでみての感想。

内容は、分散型バージョン管理システムの1つであるGitの使い方(そう、「使い方」)を、マンガを交えながら学んでいくものとなっている。
Gitというと何やら難しいイメージがあるけど、この本ではマンガのおかげもあって、そういった難しさは全く感じられないようになっている。
これはいいw

ツールとしては、コマンドラインベースではなく、GUISourceTreeを使っている。
しかも、操作手順をちゃんと画像を入れながら説明してくれるという親切設計w
プログラマならコマンドラインでも何も問題ないと思うけど(というか、自分は基本的にはコマンドラインXcodeからしか使わないけど)、これはコマンドに慣れていない人にすごくいいと思う。
(逆にいうと、コマンドの説明は全然ないので、コマンドで使うつもりの人はちょっと注意)

Gitを個人のバックアップツールとして使うところから始まって、複数人で使う基本的な使い方、それに、GitHubやBitbacketを使ったソーシャルコーディングまで、基本的な話はちゃんと入っている感じ。
とりあえずこれを読んで、あとは必要に応じて調べれば、一通り使えるんじゃないかな。

ただ、自分は一応Gitを知っているので、その観点での感想なのが気になるところ。
Gitを全然知らない人が、この本を読んで理解できるのかは、正直ちょっと分からない。
すごく分かりやすそうに書いているので、たぶん大丈夫だと思うんだけど、その「分かりやすそう」が本当に分かりやすいのか、マンガのせいでそう感じさせられているだけなのか、そのあたりが、すでにGitを知っている自分からは判断できなかった。

例えばだけど、「『Git』をどう読むのか」という割と典型的な部分の説明がなかったり。
「ギット」と読むわけだけど、GIF(ジフと発音されることが多い)に慣れてると、「ジット」と読んでしまってもおかしくないわけで。
(実際、自分は昔、間違えて「ジット」だと思ってた)
まぁ一応、表紙のタイトルの「Git」にそっと添えるように「ギット」と書かれていたり、初めて「Git」という単語を聞いた(主人公の)わかばちゃんが次のコマで「ギット?」というセリフを言ってたりはするけど。

そんな感じで、Gitに慣れ親しんでしまった身には当然になりすぎてしまっていて、初心者には実はよく分からないという内容が紛れ込んでしまってるんじゃないかなぁ、というのが、気になるところ。

あと、個人的に気になったところがいくつか。

マージすべきかリベースすべきかという話があるけど、その両方に触れてはいるものの、実際にどちらにすべきかについては言及していなかったり。
自分も昔はリベースすげぇとリベース大好きだったけど、次のスライドを見てからは、リベースではなくマージを行う運用を使うようにしている。

Subversionに慣れていて、branchはtrunkへマージするものという意識があったので、その逆の、trunkをbranchにマージする(Gitの場合、masterブランチをtopicブランチにマージする)という発想はかなり衝撃的だった。
ただ、このスライドのいうとおり、マージをmasterブランチ側ではなくtopicブランチ側で行うようにすれば、マージの記録が残る上に、masterブランチへの反映のタイミングでは絶対にコンフリクトが発生しないので、とてもいい。

それと、これは自分がGitHubでforkを行なったことがないからなんだけど、forkしたリポジトリでfork元のリポジトリの変更をどうやって取得するのかなぁ、と。
これについて、本では言及なし。
こういうところがあるので、最初に書いた「Gitを知らない人がホントに理解できるのか分からない」という感想も出てきたのだけど・・・
おそらく、fork元のリポジトリをremoteリポジトリとしてローカルのリポジトリに追加した後、ローカルのリポジトリにfork元のコミットをfetchしてきて、そこから自分がforkしたリポジトリにpushするのかなぁ、と思っているけど、そんなメンドイ手順が必要なんだろうか・・・?

まぁ、上記の2つは、基本というよりかは実際の運用上の問題なので、この本には書いてなくても当然という気もするけど。

何はともあれ、こうやって気軽にGitの使い方を学べるのは、とてもいいなと思った。
Gitを使える人がもっと増えるといいなw

今日はここまで!

わかばちゃんと学ぶ Git使い方入門〈GitHub、Bitbucket、SourceTree〉

わかばちゃんと学ぶ Git使い方入門〈GitHub、Bitbucket、SourceTree〉

『OS自作入門』を読んでみた。(その1)

前回、『30日でできる! OS自作入門』を読んでいることをちょこっと書いた。

30日でできる! OS自作入門

30日でできる! OS自作入門

この本では、小さなプログラムから始めて、少しずつOSっぽい機能をつけていき、最終的にはOSが出来上がるようにしている。
最初からしっかりと全体を設計して作っていくというわけではなく(もちろん、筆者の中ではやってるのかもしれないけど)、少しずつ継ぎ足し継ぎ足しでプログラムを成長させていくのが面白い。

そんな本なので、実際に手を動かしながら、自分でも動くものを作っていくのが面白いかな、と。

最初のOS?

ということで、最初のOSっぽいプログラム。
まぁ、ブートして文字列を出力するだけのプログラムなんだけどw
しかも、それをアセンブラで書くというわけではなく、イメージをバイナリエディタで作るというw

本ではBzというバイナリエディタを使っているんだけど、自分はMacなので、これは使えず。
そこで、RubyVimを使って同じバイナリイメージを作ってみた。

空データのファイルの作成

フロッピーディスクのディスクイメージを作るんだけど、そのサイズは1440KBで、しかもそのほとんどは空のデータ(0x00)。
これを全部手打ちするのは無駄なので、まずは全部0x00で埋まった1440KBのファイルを作ることにした。
そして、あとで必要な部分を修正していく。

全部0x00で埋まった1440KBのファイルは、Rubyを使ったワンライナーでサクッと。

$ ruby -e 'print "\x0" * 1440 * 1024' > hello-os.img

出来たファイルの中身を見てみると、次のような感じ:

$ hexdump -C hello-os.img
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00168000

1440Kは1474560(=1440x1024)で、これを16進数にすると0x168000なので、これでOK。

Vimを使ったバイナリファイルの編集

空データのファイルは出来たので、あとはこれをVimで編集していく。

Vimでバイナリファイルを編集する場合、-bオプションをつけて起動する:

$ vi -b hello-os.img

起動すると、こんな感じ:

f:id:yamaimo0625:20170422161403p:plain

^@(=0x00)がたくさん並んでいるのが分かると思う。

このままではさすがに編集できないので、編集しやすいようにする。
そのとき使うのが、xxdというコマンド。
このコマンドは、バイナリデータを見やすい16進数表示のテキストに変換してくれたり、逆に、16進数表示のテキストをバイナリデータに変換してくれたりする。

exモードで、以下を実行:

:%!xxd -c 16 -g 1

すると、こんな表示になる:

f:id:yamaimo0625:20170422162012p:plain

ちなみに、-c 16 -g 1はオプションで、なくてもOK。
-cは1行に何バイトずつ表示させるかを指定するオプションで、-gは1列に何バイトずつ表示するのかを指定するオプションになっている。
デフォルトだと1列に2バイトずつ表示され、リトルエンディアンなのかビッグエンディアンなのか分からず戸惑ったので、1列には1バイトずつ表示するようにしている。
(ちなみに、デフォルトだとビッグエンディアンなので、例えば0102 0304 ...と表示されていたら、メモリ上も0x01 0x02 0x03 0x04 ...とデータは並んでいる)

この状態で、バイト列の16進数を本に書かれた通りに修正していく。
これは、テキストファイルを修正しているだけなので、普通に編集すればいい。
すると、以下のような感じ:

f:id:yamaimo0625:20170422162910p:plain

あとは、このテキストファイルをバイナリデータとして書き戻してやるだけ。
それには、xxdコマンドに-rオプションをつけて実行すればいい。

ということで、exモードで以下を実行:

:%!xxd -r -c 16 -g 1

すると、こんな感じ:

f:id:yamaimo0625:20170422163401p:plain

データが書き換わっているのが分かると思う。

保存して中身を確認してみると、次のようになっている:

$ hexdump -C hello-os.img
00000000  eb 4e 90 48 45 4c 4c 4f  49 50 4c 00 02 01 01 00  |.N.HELLOIPL.....|
00000010  02 e0 00 40 0b f0 09 00  12 00 02 00 00 00 00 00  |...@............|
00000020  40 0b 00 00 00 00 29 ff  ff ff ff 48 45 4c 4c 4f  |@.....)....HELLO|
00000030  2d 4f 53 20 20 20 46 41  54 31 32 20 20 20 00 00  |-OS   FAT12   ..|
00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000050  b8 00 00 8e d0 bc 00 7c  8e d8 8e c0 be 74 7c 8a  |.......|.....t|.|
00000060  04 83 c6 01 3c 00 74 09  b4 0e bb 0f 00 cd 10 eb  |....<.t.........|
00000070  ee f4 eb fd 0a 0a 68 65  6c 6c 6f 2c 20 77 6f 72  |......hello, wor|
00000080  6c 64 0a 00 00 00 00 00  00 00 00 00 00 00 00 00  |ld..............|
00000090  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
00000200  f0 ff ff 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000210  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001400  f0 ff ff 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00001410  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00168000

これでイメージは完成。

動作確認

イメージが完成したので、さっそく動作確認。
前回QEMUをビルドしてあるので、そのQEMUを使って起動してみた。

$ qemu-system-i386 -fda hello-os.img 

なお、hello-os.imgはフロッピーディスクのイメージなので、-fdaオプションを指定している。

起動すると、以下のような感じ:

f:id:yamaimo0625:20170422164442p:plain

OS?が起動して、"hello, world"が表示されているのが分かると思う。

今日はここまで!

30日でできる! OS自作入門

30日でできる! OS自作入門

MacでQEMUのビルドをしてみた。

最近、『30日でできる! OS自作入門』を読んでる。

この本自体はだいぶ昔に買っていたんだけど、分厚いので完全に積読になってた。
ただ、毎度おなじみのhontoで検索してみたら、電子書籍版が出てて、これなら手軽に読めるなとポチり。
ちょうどキャンペーンをやっていたので、かなりお得だったし。

で、この本ではPC/AT互換機で動くOSを実際に作っていくんだけど、使っているのはMacだし、フロッピーディスクからの起動を想定しているので、実機を用意するのはちょっと面倒。
ということで、仮想環境で試してみようかなと。

Macで使える仮想環境としては、QEMUの他にも、無料のVirtualBoxや、有料のParallels DesktopVMware Fusionなどもある。
ただ、仕事で今後QEMUと関わってくる機会が増えそうなので、せっかくだからQEMUをインストールしてみることにした。

大まかな流れ

QEMUの公式ページを見てみると、Macの場合はHomebrewを使えば簡単にインストール出来るみたい。
ただ、せっかくなので、ソースからビルドしてみようかなと。
ページを見る限り、普通に./configureしてmakeすればいいだけのようだったから。

ただ、当然というか、実際にはこんな簡単にはいかなくて。

具体的には、以下のような手順が必要だった:

  1. autotoolsのビルド
    1. autoconfのビルド
    2. automakeのビルド
    3. libtoolsのビルド
  2. pkg-configのビルド
  3. glibのビルド
    1. libffiのビルド
    2. gettextのビルド
    3. libpcreのビルド
    4. glibのビルド
  4. QEMUのビルド

すごく大変だった・・・

autotoolsのビルド

まずはautotoolsのビルドから。

UNIX系だと、ビルドするときにtarボールをダウンロードしてきて解凍し、./configureしてmakeするのが定番だけど、この仕組みを支えているのがautotools。
具体的には、このconfigureスクリプトを設定ファイルから生成してくれたりする。

もちろん、普通は生成済みのconfigureスクリプトがtarボールには入っているので、このautotoolsを普通のユーザが使うことは基本的にはない。
けど、QEMUのGitリポジトリの場合、その下に他のGitリポジトリをサブモジュールとして取り込んでいるようなので、そのサブのリポジトリでのconfigureスクリプトを生成するのに必要っぽい。

ちなみに、autotoolsにもGitリポジトリはあるんだけど、configureスクリプトは入ってない。
じゃあ、どうやってビルドするのかといえば、autotoolsを使ってconfigureスクリプトを作るw
卵が先か、鶏が先かw

まぁ、こういう開発ツールの根幹になるツールには、よくあること。
Cコンパイラとかもそうだし。

ということで、素直にtarボールをダウンロードしてきて、ビルドする。

autoconf

まずはautoconfから。

Autoconf - GNU Project - Free Software Foundation

FTPからtarボールをダウンロードしてきて、普通にビルド。

$ tar zxvf autoconf-2.69.tar.gz
$ cd autoconf-2.69
$ ./configure
$ make
$ sudo make install

automake

続いて、automake。

Automake - GNU Project - Free Software Foundation

これも同じ。

$ tar zxvf automake-1.15.tar.gz
$ cd automake-1.15
$ ./configure
$ make
$ sudo make install

libtools

最後にlibtools

GNU Libtool - GNU Project - Free Software Foundation

$ tar zxvf libtool-2.4.6.tar.gz
$ cd libtool-2.4.6
$ ./configure
$ make
$ sudo make install

簡単w

pkg-configのビルド

autotoolsのビルドが出来たら、次はpkg-configのビルド。

pkg-config

このツールは、configureスクリプトを走らせときに、ライブラリの情報を得るのに使われるツール。

ただ、実はここでも循環した依存関係が存在していて、pkg-configを動かすには後述のglibが必要なんだけど、glibのビルドにはpkg-configが必要というw

この循環依存を断ち切る一つの方法としては、あらかじめビルドされたglibをインストールしておいて、それでpkg-configをビルドするという方法が考えられる。
ただ、それでは面倒なので、pkg-configのtarボールの中には、最近の安定版のglibのコピー(のおそらく一部だけ)が入っていて、configureで指定すれば、このglibを使ってビルドが出来るようになっている。

tarボールをダウンロードしてきたら、以下のようにすればいい:

$ tar zxvf pkg-config-0.29.2.tar.gz
$ cd pkg-config-0.29.2
$ ./configure --with-internal-glib
$ make
$ sudo make install

これでOK。

ちなみに、QEMUのビルドではこうやってビルドしたpkg-configで十分なんだけど、もし後からインストールしたglibを使うようにしたいなら、--with-internal-glibの指定を外して、もう一回ビルドし直した方がいいのかもしれない。
GCCのビルドで、まず最小限のGCCを作った後、そのGCCでCライブラリを作った後、フルのGCCを作るというのに似てるかも)
(動的リンクなら大丈夫?)

glibのビルド

次はglibのビルド。

正直、これが一番大変だった・・・
というのも、依存しているライブラリが多いから。

glibはGTK+ツールキットの根っことなる機能を提供しているライブラリで、CocoaでいうFoundationフレームワークのようなもの。(のはず)
そんな根っことなるライブラリが、他のいろいろなライブラリに依存してるのもどうなんだと思うんだけど・・・

libffiのビルド

まずはlibffiのビルドから。

libffi

libffiは、ある言語から他の言語で書かれたライブラリを呼び出したりするのに使われるライブラリ。

ビルドは普通。

$ tar zxvf libffi-3.2.1.tar.gz
$ cd libffi-3.2.1
$ ./configure
$ make
$ sudo make install

gettextのビルド

続いて、gettextのビルド。

gettext - GNU Project - Free Software Foundation (FSF)

gettextは多言語化に使われるライブラリ。

これもビルドは普通。

$ tar zxvf gettext-0.19.8.1.tar.gz
$ cd gettext-0.19.8.1
$ ./configure
$ make
$ sudo make install

libpcreのビルド

次はlibpcreのビルド。

これはPerl正規表現と同じ文法の正規表現を提供するライブラリ。
なんでこんなのが必要なんだろう・・・

このビルドは以下のとおり:

$ tar zxvf pcre-8.40.tar.gz
$ cd pcre-8.40
$ ./configure --enable-unicode-properties
$ make
$ sudo make install

気をつけないといけないのが、configureスクリプト--enable-unicode-propertiesというオプションを指定していること。

最初、configureスクリプトのヘルプを見て、--enable-utfというオプションはつけてビルドしたんだけど(これがないとUTF8/16/32のサポートも有効にならない)、それだけだと不足で、glibのビルドに失敗した。
--enable-unicode-propertiesというオプションをつけておけば、--enable-utfも有効になり、glibのビルドも問題なくなる。

glibのビルド

ここまでやって、やっとglibのビルド。

まず、glibのtarボールを落とすのが大変w
もちろん、Gitリポジトリをcloneしてビルドしてもいいんだけど、configureスクリプトが入ってないので、ちょっと面倒。

自分は以下のFTPから落としてきた:

https://ftp.gnome.org/pub/gnome/sources/glib/2.52/

ビルドは以下のとおり:

$ tar Jxvf glib-2.52.1.tar.xz
$ cd glib-2.52.1
$ CFLAGS="-I/usr/local/include -L/usr/local/lib" ./configure
$ make
$ sudo make install

ちなみに、configureの前でCFLAGSを指定しているのは、こうしないとgettextの提供するヘッダファイルとライブラリをなぜか見つけられなかったから。

長かったけど、これでやっとglibのビルドが完了。

QEMUのビルド

残すはQEMUのビルドのみ。

まずは、QEMUのGitリポジトリをローカルにcloneしてくる:

$ git clone git://git.qemu-project.org/qemu.git
$ cd qemu
$ git submodule init
$ git submodule update --recursive

前述したとおり、QEMUのGitリポジトリは、その下に他のGitリポジトリをサブモジュールとして取り込んでいるので、その初期化とアップデートも行なっている。

これであとは./configureしてmakeすれば終わり・・・ならよかったんだけど、そうは問屋が卸さず。

Macの場合、pixmanというサブモジュールに問題があるらしく、makeすると以下のエラーが出てしまった:

pixman-mmx.c:100:20: error: constraint 'K' expects an integer constant expression

調べて見ると、以下のスレッドで議論がされていて、よく分からないけど、なんとなく新しいバージョンにすれば直ってそう。

The Pixman October 2015 Archive by thread

ということで、pixmanを0.33.6のブランチに切り替えてみた。

$ git checkout topic/local_bugfix   # 適当な名前でバグフィクス用のブランチを用意
$ cd pixman
$ git checkout pixman-0.33.6
$ cd ..
$ git add pixman
$ git commit
$ git submodule update

そのあと、./configuremake

これで先ほどのエラーは出なくなったんだけど、これでも以下のエラーが出た:

Undefined symbols for architecture x86_64:
  "_prng_state", referenced from:
      _main in region-test.o
  "_prng_state_data", referenced from:
      _main in region-test.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

ただ、これは調べてみるとテストコードの問題らしく、とりあえず実害はないっぽい。
なので、エラーが起きた後にtouchコマンドで仮のファイルを作ってやれば、ビルドがスキップされて大丈夫とのこと。
(なぜかエラーが起きる前にtouchコマンドを使うとファイルが削除されてしまったので、エラーが起きた後にやった方が確実かもしれない)

$ touch pixman/test/region-test
$ touch pixman/test/scaling-helpers-test

(参考: Qemu 2.3.0 released! | Fun with virtualization

これでQEMUのビルドも完了!

ちなみに、デフォルトの設定でビルドすると、全部のアーキテクチャがビルドされる。
なので、特定のアーキテクチャだけビルドしたい場合には、configureスクリプト--target-list=LISTオプションを指定してやるといい。
(LISTをビルドしたいアーキテクチャにする)

利用可能なアーキテクチャは、./configure --helpをやれば見ることが出来る:

$ ./configure --help

Usage: configure [options]

(省略)

  --target-list=LIST       set target list (default: build everything)
                           Available targets: aarch64-softmmu alpha-softmmu 
                           arm-softmmu cris-softmmu i386-softmmu lm32-softmmu 
                           m68k-softmmu microblaze-softmmu microblazeel-softmmu 
                           mips-softmmu mips64-softmmu mips64el-softmmu 
                           mipsel-softmmu moxie-softmmu nios2-softmmu 
                           or1k-softmmu ppc-softmmu ppc64-softmmu 
                           ppcemb-softmmu s390x-softmmu sh4-softmmu 
                           sh4eb-softmmu sparc-softmmu sparc64-softmmu 
                           tricore-softmmu unicore32-softmmu x86_64-softmmu 
                           xtensa-softmmu xtensaeb-softmmu

(以下略)

動作確認

これでやっとQEMUのビルドも終わったので、動作確認をしたいところ。

以下のページでテスト用のイメージがいくつか用意されていた:

Testing/System Images - QEMU

なので、それを使って動作確認してみた:

とりあえずlinux-0.2.img.bz2というイメージをダウンロードしてきて解凍し、以下のようにして動作確認:

$ qemu-system-i386 linux-0.2.img

すると、次のような画面が現れる:

f:id:yamaimo0625:20170417000323p:plain

これで問題なく動作してることが確認できた。

ちなみに、ウィンドウ内をクリックするとマウスの制御がゲスト側に取られてしまうけど、Ctrl+Alt(Macの場合、Ctrl+Option)を押すことで、マウスの制御はホスト側に戻ってきてくれる。
終わらせるときは、メニューから終了を選べばOK。

今日はここまで!

手帳ネクロで遊んでみた。

またまたシャドウバースの話w

3月末に新カードパックの「神々の騒嵐」がリリースされて、環境もガラッと変わって面白いことになってる。

アグネクの活躍

特に驚いたのが、アグネク(アグロネクロ)の活躍。

リリース直前は、ドラゴンに「ライトニングブラスト」とかいうネクロ殺しのカードが追加されることが発表され、それに対してネクロ勢が最後の最後に期待していたシルバーレアのカードが「骨の貴公子」というかなり地味な印象のカードだったので、もうお葬式も同然の空気だった。
これはもう新カードパックがリリースされたら、ネクロは息してないんじゃないかな、と多くの人が思ってた。

が、蓋を開けてみれば、アグネクが環境で一番使われているというw
その原因は、何を隠そう、かなり地味な印象だった「骨の貴公子」の活躍で、このカードのおかげで盤面にフォロワーが残りやすくなって、バフを効かせて殴りにいったり、息切れせずに攻めが続くようになった。
「ゾンビパーティ」「破魂の少女」「骨の貴公子」「オルトロス」といった、書かれていることは確かに弱くはないんだけど、他のクラスに追加された派手で強力なカードと比べると一段も二段も見劣りするような追加カードたちが、恐ろしいまでのシナジーを発揮して、アグロデッキとして強烈なまでの破壊力、戦闘継続能力を発揮するようになっている。
(だが、「魂の番人・ミント」、お前はダメだ・・・可愛いのに・・・)

手帳ネクロ

さて、そんな環境トップで活躍しているアグネクはさておき、自分がよく使って遊んでいるのが、手帳ネクロというデッキ。

これは、やはり新カードパックで追加された「死神の手帳」というカードを軸にしたミドルレンジ〜コントロール寄りのデッキで、かなり面白い動きをするw
勝てるかは別としてw

f:id:yamaimo0625:20170406233615p:plain

「死神の手帳」の効果は、ターンの終わりに、今のPPよりコストの低いネクロマンサーのフォロワーを自分のデッキからランダムに1体出して、それを破壊する、というもの。
それが2ターンほど続く。
フォロワーを出してもすぐに破壊されてしまうんじゃ、意味なさそうだけど、ネクロマンサーのフォロワーはラストワード持ちーーすなわち、破壊されたときに能力を発揮するフォロワーがいるので、その効果を引き出すことが出来る。
もちろん、そういうフォロワーが引けるようにしておかないといけないので、構築には少し工夫が必要だけど。

ということで、組んでみたのが、次のデッキ。

ネクロマンサーのフォロワーは、「闇の従者」「地獄の解放者」「デュエリスト・モルディカイ」に絞ってあって、死神の手帳では基本的に「闇の従者」か「地獄の解放者」が引かれるようになっている。
この2つのフォロワーは、破壊されると「リッチ」という4/4(攻撃力4、体力4ということ)のフォロワーを出すので、なかなか強い。
(ちなみに、「デュエリスト・モルディカイ」は、破壊されると「デュエリスト・モルディカイ」を出す。つまり、消滅させられない限り、ずっと残るw)

あとポイントとなるのが、「ウリエル」。
このカードはアミュレットをデッキから手札に引っ張ってきてくれるので、これで「死神の手帳」を確定で手に入れることが出来る。
なので、結構な確率で「死神の手帳」をプレイできるようになっている。

プレイしてみて

ちなみに、プレイしてみると、「死神の手帳」を出す瞬間がめちゃくちゃ弱いw
最速で4ターン目だけど、そこはもう進化が可能になっているターンなので、進化を使って盤面の取り合いが行われるのが普通なんだけど、そこで進化を使えないでただ4/4のフォロワーを出すだけだから、ホントに弱い(^^;

けど、その分、次のターンに強い動きが出来るというのがかなり面白い。
そのターンのPPを使い切った上で、無料で4/4のフォロワーが追加で出てくるわけで、実質+4PPの動きが出来ている。
このおかげで、一度は盤面を取られても、取り返してさらに「リッチ」を場に並べるなんてことも可能。

例えば、こんな盤面になったりするw

f:id:yamaimo0625:20170407003054p:plain

f:id:yamaimo0625:20170407003103p:plain

これは楽しいw

あと、「死神の手帳」はフォロワーを破壊をしてくれるので、墓地が増えるというのも嬉しかったり。
ビショップ相手だと、消滅させられて墓地が増えず、結果、「ファントムハウル」や「死の祝福」といった、墓地を使って強力な効果を発揮するカードが使えなかったりすることが多いのだけど、この手帳ネクロなら、墓地がちゃんと増えてくれるので、これらのカードを有効に活用できたり。
それに、消滅させられるのは体力3以下のフォロワーであることが多いので、体力が4あるリッチは消滅させられにくいというメリットもあったりする。

さらには、デッキからフォロワーを召喚して破壊するので、デッキの圧縮にもなっているのが嬉しいところ。
デッキの枚数が減れば、それだけ欲しいカードの引ける確率も上がってくる。

そんななかなか面白いデッキなんだけど、弱点も。

まず、相手を指定せずに除去を行うカードがない。
なので、潜伏を使ったデッキ(特に「旅ガエル」デッキ)には、めっぽう弱い。
一応、構築で「よろめく不死者」とかを入れれば、対処は出来なくはないんだけど、「死神の手帳」で出る効果がランダムになってしまって、狙った効果が出ないとかなりキツい。

次に、どうしても速度が遅いので、下手すればアグネクに轢き殺される(^^;
特に、後攻になってしまうとかなりツラい。

さらに、今アグネクとトップを争っているドラゴンに対しても、ターンが遅くなってくれば強力なカードを持つドラゴンが圧倒的に強くなってくるので、かなり厳しい。
特に、「ライトニングブラスト」を打たれると、リッチ軍団もモルディカイも死神の手帳それ自体も消滅させられてしまうので、もう無理。

そんな感じで、決して弱いわけではないんだけど、今の環境ではなかなか勝てない感じではある・・・
楽しくはあるんだけど。


まぁ、なにはともあれ、「リッチ」を並べて盤面を圧倒するというのは、実現できればかなり気持ちがいいので、ぜひお試しあれ。

今日はここまで!

シャドウバース (Shadowverse)

シャドウバース (Shadowverse)

  • Cygames, Inc.
  • ゲーム
  • 無料

「交換」について考えてみた。

昔のブログに書いた記事から。
書いたのは2004年9月3日で、書いた時のタイトルは『交換。』。


Chronicle 2ndを聞いていて、ふと思ったことのメモ。

ちなみに、まったく余談ながら、このCDめちゃくちゃいいw
オペラも好きだけど、こういう物語のある音楽(しかも、このCDの場合、音楽自体にすごく味がある)は大好き。

で、このCDの「沈んだ歌姫」(13曲目)の中で、娘を売れだなんだと出てくる。

駈ける駆ける獣(Bestia)
高値で売れるなら娘でも売れ
売値は望む得る限り高く

猛る猛る獣(Bestia)
敵を売れ 味方を売れ
他人の娘など底値で売りつけてやれ

咆える吼える獣(Bestia)
弑逆を謀った逆賊として
デル・ビスコンティエ一門処刑

屠る屠る獣(Bestia)
逃亡を図った国賊として
デル・ビスコンティエ令嬢を処断
(『Chronicle 2nd』「沈んだ歌姫」より引用)

これを聴いてふと浮かんだのが、次のような疑問。

もし、人が娘同士を「売りあった」場合――結局それは、娘を交換し合っただけに過ぎないのだけど――売られる前と後で、娘の待遇はどう変わるのか?

例えばこれが、単純な「娘とお金の交換」であれば、どうだろう。
倫理的な問題はとりあえず置いておいて、これは「娘」という商品と「お金」との交換であり、それ相応の交換が行われたと考えられる。
売られた娘の待遇がどうなるかは、おそらく売られる前に比べて悪くなると思われるが、買った人の一意により、そこまで考慮した上でお金のやり取りがされるだろう。

さて、ここで、これを「売りあった」とすると、どうだろう。
つまり、AとBにはそれぞれ娘がいて、Aは x円で娘をBに売り、Aはそこで手に入れた x円でBの娘を買ったとしたら、どうだろう。
お互い売りあったのだから、それぞれの娘の待遇については、単に一方がお金で娘を買ったときと同様に、買った人の一意によることになる。
しかし、お金のやり取りに目をつけてみると、AとBのどちらも x円で娘を売り、 x円で娘を買ったのだから、プラマイ0となる。
つまり、単純な「交換」だ。
すると、お金のやり取りなしに娘を交換するだけで、娘が完全に他人の手に委ねられてしまうことになる。
このことに、違和感を感じるのは自分だけだろうか・・・?

さらにいうと、この場合の x円は任意の金額になっている。
娘の価値がそれ相応の値段になっているのかどうかは全く不明であり、100円でやり取りされた可能性もある。

ーー種明かし(?)をすれば、「商品とした」からこそ交換できるのであって、そのこと(商品としたこと)が娘の価値を貶めてる。
けど、まるで「交換」自体が物の価値を下げているように見えて、すごく奇妙に思えた。

でも、この「交換」こそが経済の基礎なんだろうなぁ、と。
で、このような単純な「交換」は、「価値の損失」を生んでいくのではないかと。


まぁ、最後の部分は今から思うとちょっと的外れな感じだけど、この「売りあった」場合にその商品に値段がつかない(値段が分からない)というのは、ちょっと面白いかなと思う。
この前読んで、記事でも紹介した『21世紀の貨幣論』から考えると、債権と債務がちょうど打ち消しあって債権が余らない(=債権を示すトークンである貨幣が不要となる)ので、値段がつかないし、いくらであるかも分からない(分かる必要もない)となるわけだけど。

あと、この文章では「価値の下がる瞬間」がどこなのかを指摘しているのがけっこう重要かなと思う。

つまり、単純に見た場合、

  1. それぞれ自分の娘は大切なもの
  2. 娘を交換する ←ここで娘の価値が下がったように見える
  3. 交換した後の他人の娘は大切なものではない

となるけど、実際には、

  1. それぞれ自分の娘は大切なもの
  2. 娘を交換可能なものとする ←ここで価値が下がっている
  3. 娘を交換する
  4. 交換した後の他人の娘は大切なものではない

と、交換するタイミングではなく、交換可能なものとしたタイミングで価値が下がっているのが、この文章での指摘。
使用価値(所有による価値もここでは含むものとする)から交換価値へと転換されたタイミング(つまり、「商品」となったタイミング)で、その価値は「個人にとっての主観的な価値」ではなく「市場内での客観的な価値」で測られることになり、それぞれの価値(使用価値と交換価値)にギャップが存在するというのが、いろいろ分析していくときに重要な視点を与えてくれそう。

今日はここまで!

ワイヤレスイヤホンを買ってみた。

ワイヤレスイヤホンを買ってみたので、その話など。

きっかけ

まず、なんでワイヤレスイヤホンを買おうと思ったのかというと、iPhone 7のイヤホン変換ケーブルが断線したから。
これまでのイヤホンも気に入っていたし、新しいケーブルを買ってもよかったんだけど、正直この変換ケーブルが煩わしかったので、これを機に買い換えようかなと。

ちなみに、これまで使ってたイヤホンは、コレ。

信頼のオーティオテクニカw
自分は低音が大好きなので、SOLID BASSシステムとやらで重低音がしっかりと聞けるのが嬉しい。
あと、イヤホンを入れる用のケースがついてて、これがけっこう使い勝手よかったw

ヨドバシカメラ

そんなわけで、ヨドバシカメラへ。

最初に買おうと思っていたのは、オーティオテクニカのコレ。

これまで使ってたCKS99の後継ともいえるCKS990のワイヤレス版。

ただ、実際に視聴してみると、ちょっと微妙な感じ。

  • 重低音が思っていたより微妙
  • 首にかける部分がバネのように弾力性のある素材で、煩わしい

まぁ、これは店頭で試したので、エイジングが十分でないとか、ケーブルで繋がれてたからとかも考えられるんだけど。

けど、そんなだったので、イヤホン探しは一からやり直し。
いろんなワイヤレスイヤホンを試してみた。

そんな中で、「これは!」というのを見つけた。
それが、こちら。

f:id:yamaimo0625:20170402191148p:plain

フィリップスのTX2BT。

最初、見た目がなんか高級感あるなぁと手に取ったんだけど、視聴してみてビックリ。
重低音のクリア感が凄い。

イヤホンを買うとき、自分が視聴によく利用しているのが、梶浦さんの「Key Of The Twilight」。

この曲を支えている低音部分が、しっかりと重低音を鳴らしてくれるイヤホンだとホント見違えるように違ってくるから。
実際、いくつか試したイヤホンで、他の曲だとまぁまぁかなぁ、と思っていたものも、この曲を聞いてみると、低音部分が全然響いてなくて全然ダメダメだったと気付くことがあったり。
逆に、低音が強くなり過ぎて、高音部や音声域がくぐもってしまったり、安っぽくなってしまうということもよくあるけど、この曲だとそういうのにも気付くことが出来る。

で、このイヤホンでもこの曲を聴いてみたんだけど、重低音がしっかりと聞こえる上に、そのクリア感が凄かった。
下から2番目のタッタカタッタカタッタカタッタッというリズムを弾いているベースの音のクッキリ感が凄くて、こんなにクッキリと聞こえるものなのかと。
もちろん、一番下のベースもちゃんと鳴ってるし、高音部や音声域もバランス良く鳴ってる感じ。

お値段的にも悪くなかったので、これを購入。

その後

ただ、問題はこの後。

帰ってから開けてつけてみたら、なんか右耳の方からカチャカチャ音がする(^^;
イヤーピースを外してみたり変えてみたりいろいろやったんだけど、改善されず。

仕方ないので、再びヨドバシに行って確認してもらい、交換してもらった。

と、そしたら今度は右耳の音が出ないw

ここまでハズレを引かされるかと辟易したんだけど、幸い、もう一度交換してもらって、今度こそは大丈夫になった。

アマゾンのレビューを見てみると、同様にカチャカチャ鳴ったというレビューが一つ見つかったので、けっこう不良品があるのかも。
なので、買うときはちゃんと交換に応じてくれるお店で買った方がいいかもしれない。

何はともあれ、モノはいいと思うので、ワイヤレスイヤホンを買おうと思っている人は、選択肢の一つにぜひ!

今日はここまで!