追記 NASMでの構造体の参照
気になって調べてみた。こっちのほうがシンプルに書ける気がする。
struc mytype
NASM - The Netwide Assembler
mt_long: resd 1
mt_word: resw 1
mt_byte: resb 1
mt_str: resb 32
endstruc
あとは"mov ax,[mystruc+mytype.word]"のような形で利用する。
GAS(GNU Assembler)で構造体にアクセスする
環境はWindows7(32bit)&cygwinのgcc/gas(x86)で試した。
".struct"で構造体を定義し、その後サイズ(item_length)を算出する。
そして".bss"セクションに構造体名(item)でitem_length分メモリーを確保(".space")する。
後は、レジスタにitemのアドレスを代入し、間接アドレッシングでメンバーにアクセスする(この例ではitem.item2に0x05を代入している)。
.struct 0 item_start: item1: .struct item1 + 12 item2: .struct item2 + 2 item3: .struct item3 + 8 item_end: item_length = item_end - item_start .bss item: .space item_length .text movl item,%eax movw $0x05,item2(%eax)
コンパイルし逆アセンブラをしてみると確かにitem2の位置(12→0xc)分を考慮したコードが生成されていた。
$ objdump.exe -d st.o セクション .text の逆アセンブル: 00000000 <.text>: 0: a1 00 00 00 00 mov 0x0,%eax 5: 66 c7 40 0c 05 00 movw $0x5,0xc(%eax) b: 90 nop
次のステップとして、アセンブラからC言語の構造体(ヘッダに定義)にアクセスしたいのだけど、やり方がよくわからない。インラインアセンブラを使えばこんな苦労しないのだけど...。
参照:
Ian Lance Taylor - Re: structures in assembly code
Using as: Struct
xv6をWindows環境(cygwin環境)で手軽にビルドする
cygwinのgcc(binutil)だと出力可能なバイナリーフォーマットが原因で、自作OSのビルドが出来ないケースが多々ある。
そこで、cygwinportsを利用しgccを導入することでこの問題を解決する。
ついでに今回はxv6をビルドしてみた。
cygwin & apt-cyg の導入までは色々解説があるので適当にお願いします。
クロス開発環境を導入する。
$ apt-cyg update -m ftp://ftp.cygwinports.org/pub/cygwinports $ apt-cyg install linux-i686-gcc-core (省略) $ i686-pc-linux-gnu-gcc -v 組み込み spec を使用しています。 COLLECT_GCC=i686-pc-linux-gnu-gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-pc-linux-gnu/4.8.2/lto-wrapper.exe ターゲット: i686-pc-linux-gnu configure 設定: /usr/src/ports/linux-i686-gcc/linux-i686-gcc-4.8.2-1/src/gcc-4.8.2/configure --srcdir=/usr/src/ports/linux-i686-gcc/linux-i686-gcc-4.8.2-1/src/gcc-4.8.2 --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --libexecdir=/usr/libexec --datadir=/usr/share --localstatedir=/var --sysconfdir=/etc --libdir=/usr/lib --datarootdir=/usr/share --docdir=/usr/share/doc/linux-i686-gcc --htmldir=/usr/share/doc/linux-i686-gcc/html -C --build=i686-pc-cygwin --host=i686-pc-cygwin --target=i686-pc-linux-gnu --without-libiconv-prefix --without-libintl-prefix --with-sysroot=/usr/i686-pc-linux-gnu/sys-root --with-build-sysroot=/usr/i686-pc-linux-gnu/sys-root --libexecdir=/usr/lib --enable-shared --enable-shared-libgcc --enable-static --enable-languages=c,c++,fortran,ada,java,go,lto,objc,obj-c++ --enable-version-specific-runtime-libs --disable-alsa --enable-libada --enable-libgomp --enable-libitm --enable-libjava --enable-libquadmath --enable-libquadmath-support --enable-libssp --enable-default-preferences-peer=file --disable-java-awt --disable-jni --with-arch=i686 --with-tune=generic --with-dwarf2 --with-ecj-jar=/usr/share/java/ecj.jar --with-gnu-as --with-gnu-ld --with-cloog-include=/usr/include/cloog-isl --with-system-zlib スレッドモデル: posix gcc バージョン 4.8.2 (GCC)
導入成功!
xv6のMakefileを書き換えビルドする。
xv6のソースを展開し、Makefileの"TOOLPREFIX"を"TOOLPREFIX = i686-pc-linux-gnu-"と設定。
後はmakeするだけで完成する
$ make i686-pc-linux-gnu-gcc -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pic -O -nostdinc -I. -c bootmain.c i686-pc-linux-gnu-gcc -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pic -nostdinc -I. -c bootasm.S i686-pc-linux-gnu-ld -m elf_i386 -N -e start -Ttext 0x7C00 -o bootblock.o bootasm.o bootmain.o i686-pc-linux-gnu-objdump -S bootblock.o > bootblock.asm i686-pc-linux-gnu-objcopy -S -O binary -j .text bootblock.o bootblock ./sign.pl bootblock boot block is 447 bytes (max 510) i686-pc-linux-gnu-gcc -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer -fno-stack-protector -c -o bio.o bio.c (省略) i686-pc-linux-gnu-gcc -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer -fno-stack-protector -c -o wc.o wc.c i686-pc-linux-gnu-ld -m elf_i386 -N -e main -Ttext 0 -o _wc wc.o ulib.o usys.o printf.o umalloc.o i686-pc-linux-gnu-objdump -S _wc > wc.asm i686-pc-linux-gnu-objdump -t _wc | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$/d' > wc.sym i686-pc-linux-gnu-gcc -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer -fno-stack-protector -c -o zombie.o zombie.c i686-pc-linux-gnu-ld -m elf_i386 -N -e main -Ttext 0 -o _zombie zombie.o ulib.o usys.o printf.o umalloc.o i686-pc-linux-gnu-objdump -S _zombie > zombie.asm i686-pc-linux-gnu-objdump -t _zombie | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$/d' > zombie.sym ./mkfs fs.img README _cat _echo _forktest _grep _init _kill _ln _ls _mkdir _rm _sh _stressfs _usertests _wc _zombie used 29 (bit 1 ninode 26) free 29 log 10 total 1024 balloc: first 394 blocks have been allocated balloc: write bitmap block at sector 28 dd if=/dev/zero of=xv6.img count=10000 10000+0 レコード入力 10000+0 レコード出力 5120000 バイト (5.1 MB) コピーされました、 0.271833 秒、 18.8 MB/秒 dd if=bootblock of=xv6.img conv=notrunc 1+0 レコード入力 1+0 レコード出力 512 バイト (512 B) コピーされました、 0.0163324 秒、 31.3 kB/秒 dd if=kernel of=xv6.img seek=1 conv=notrunc 248+1 レコード入力 248+1 レコード出力 126980 バイト (127 kB) コピーされました、 0.0212534 秒、 6.0 MB/秒
xv6.imgが無事に完成!ちゃんと起動する!
参考になるx64アセンブラの情報
Assembly Programming on x86-64 Linux
→linux上でx64(amd64)のアセンブラを利用したコードの紹介
参考にできる64bit自作OSの例
ソースコードが公開されていると、わからないことを確認できるので助かる。
Programming a 64-bit Operating System
→64bit OSの作成方法を説明している。アセンブラはNASMを使っている模様。
https://github.com/neri/op05
→国産64bit OSとして初期のころ有名だったOrangePekoのfork
GitHub - swetland/xv6: 64bit port of xv6
→有名なXV6の64bit移植版
64bit OS(x64 Kernel)の自作のために(1)
前から気になっていたところ、以下Blogで実際に動くコード(x86->x64)が公開されていたので、BlogとOSDEVの記事を参考にしながら動かしてみた。
ビルド環境はWindows7 with Cygwin(x86_64-pc-linux-gnu-gcc ver 4.8.2)
このとき、はまったのがx64でのGDT(Global Descriptor Table)の設定。
IDT(Interrupt descriptor table)と同じくbaseのアドレス設定値が64bitアドレスに拡張されているという別の記事を信じてしまったところ、うまくいかず四苦八苦。真相はx64でGDTのbase/limitは拡張されていないが正しい。
以下、処理の流れ。
- GRUB2で32bit Kernel(multiboot形式)をロードする。(以下32bitコード)
- 32bit/64bit用のGDTを作成する。
- 32bit用のGDTを読みこむ & セグメントを設定する。
- Pagingの有効化()
- PAEの有効化(CR4を設定する)
- Long Mode(64bitコードに移行 このとき64bitのセグメントを読み込ませる)のコードにJMPする。
- C言語のKernelを呼び出す。
参照:
Linuxをはじめよう!:1から創る自作OS x86_64 01h
Creating a 64-bit kernel - OSDev Wiki
「USB-Blasterもどき」をPIC/AVRライターが無い環境から作成する。
ここしばらく色々ありすぎて、バタバタしていたがやっと落ち着いてきたので、久々に更新することにした。
なんとなくFPGA/CPLDに興味を持ったが入門キットでも結構な値段がする。
安いキット(キットで約1,600円)はあるが書き込むための機材(USB-Blaster)が別途必要であり、結局良い値段になってしまう。
<MAX2 CPLDボードの特徴>
MAX2 CPLD
570ロジックエレメント(LE)、76I/OのEPM570T100C5Nを搭載
...(省略)
調べるとこの互換機を作っている方の記事を見つけたが、当方の環境にはこの作成に必要なPIC18F14k50にファームウェアを書き込めるライターが無い…。
・概要
USB-Blasterもどきの製作 - sa89a.net
AlteraのUSB接続JTAGインターフェース、「USB-Blaster」を安価なPICマイコンエミュレートします。
Alteraの純正ツールでCPLD、FPGAの書き込み、デバッグがUSB一本でできます。
そこで色々と検討した結果、以下順序でPICライターが作れるハズと、勉強がてら試してみることにした。
- hidspx内蔵のEGGライタ機能でHIDaspxを作成する(AVRライターを作成する)
→「http://www-ice.yamagata-cit.ac.jp/ken/senshu/sitedev/index.php?AVR%2FHIDaspx#content_1_15」を参考にした。
この方法を採用したのは、USBシリアル変換(秋月電子製)が利用できる点である。
- HIDaspx(AVRライター)でAVRにHIDaspxに書き込む。
→「http://www-ice.yamagata-cit.ac.jp/ken/senshu/sitedev/index.php?AVR%2FHIDaspx#content_1_6」を参考にした。
この作業が必要なのは、EGGライタ機能で書き込んだ場合、書き込み後のベリファイができないためである。
- HIDaspxでPIC(PIC18F14k50)に「USB-Blasterもどき」のファームウェアを書き込む(AVRライターでPICに書き込む)
→「PICspx - AVR etc」を参考にした。
これでPIC(PIC18F14k50)に「USB-Blasterもどき」のファームが書き込めた。