タイトル/名前 | 更新者 | 更新日 |
---|---|---|
日記/2010/05/11/伊豆・宇佐美(AOW講習) | msakamoto-sf | 2010-05-13 20:08:30 |
Assembler/なぜx86ではMBRが"0x7C00"にロードされるのか?(完全版) | msakamoto-sf | 2010-05-13 11:07:47 |
日記/2010/05/09/"珠玉のプログラミング"読書メモ | msakamoto-sf | 2010-05-09 10:30:30 |
日記/2010/05/09/GWは古い自作PCの処分で潰れた。 | msakamoto-sf | 2010-05-09 10:01:46 |
日記/2010/05/07/消費者用口蹄疫メモ | msakamoto-sf | 2010-05-07 20:58:26 |
日記/2010/04/28/アリとキリギリスの話ってイソップが元なのね。 | msakamoto-sf | 2010-04-28 23:04:12 |
日記/2010/04/12/フリーのWindowsリソースエディタ "ResEdit" | msakamoto-sf | 2010-04-13 12:59:10 |
日記/2010/04/12/XNResourceEditorで同じID, 異なる言語の文字列リソースがうまく取得出来ない。 | msakamoto-sf | 2010-04-13 12:54:31 |
技術/歴史 | msakamoto-sf | 2010-04-07 13:57:15 |
技術/歴史/FAQ/VGAとVESA | msakamoto-sf | 2010-04-07 13:50:17 |
5/10, 5/11 と伊豆は宇佐美でPADI AOW講習でダイビングしてきました。
デジカメ持って潜り、インストラクターに肩を掴んで固定して貰い(w、ようやく「何が写ってるのか分かる」レベルの写真を何枚か紹介します。
まずは一番綺麗に撮影できた越冬クマノミ:
宇佐美では、大抵のクマノミは越冬中に寒さで昇天されてしまうようで、今の時期まで生き延びることができるのは珍しいそうです。
English Version: " Why BIOS loads MBR into 0x7C00 in x86 ? "
Assembler/なぜx86ではMBRが"0x7C00"にロードされるのか?で調査が不十分だった点を補った完全版です。
自分がx86アーキテクチャの、特にOSのブートする仕組みやプロテクトモードを学習した時、MBR(Master Boot Record)で最初の一歩を踏み出した。MBRはフロッピーディスク(FDD)やHDDの最初の1セクタ:512バイトブロックである。OSをブートする機械語のプログラムと、ディスクの論理パーティション情報が格納されている。Interlの80x86系列のCPUを採用しているPCは、電源投入後、まずBIOSのPOST(Power On Self Test)が行われ、周辺機器が認識された後、MBRを読み込んでOSのブート処理を開始する。
BIOSはROMチップに書き込まれている為通常は変更出来ない(EEPROMなど、書き換え可能なROMを使っており、BIOSアップデートなどの特殊なソフトウェアを使うことで書き換えることができる)。一方のMBRはFDD/HDDの最初の1セクタということで、プログラマ自身が書き換えることが可能である。
2010年現在、Bochs, QEMU, VirtualBox, VMwareなどの仮想環境を手軽に活用できる環境が整っている。
そうした仮想環境を利用すれば、仮想環境用のディスクイメージファイルのMBR部分に好きな機械語を書き込むだけで、手軽に機械語の実験を行うことが可能になる。ホストOS側の現実の物理HDDのMBRを書き換えてOSが立ち上がらなくなる心配も無い。
多くの書籍やWebの記事では次のような流れでMBRのコードが実行される、と説明している。
MBRから直接OSのカーネルをロードするのではなく、一つ or 二つ程度の中間ローダを介する場合もある。MBRの機械語コード、およびMBRがロード&実行する中間ローダはOS固有の場合(MicrosoftのNTLDR)もあれば、複数のOSに対応したオープンソースソフトウェアの場合(LILO, GRUB)もある。
ところで、実際にMBRを弄った人は、次の疑問を抱いたことはないだろうか?
「"0x7C00"って、どこの仕様書で決められているんだろうか?」
x86CPUについて学んでいくと、独特の"メモリアドレスのマジックナンバー"がいくつかあることに気づく。
これは割り込みベクタ用のメモリ空間で、
4バイトの割り込みハンドラのアドレス x 256個の割り込みベクタ = 1024バイト = 0x400 バイト
で、x86の仕様として割り込みベクタはアドレス0番地から始まる為、一つ分ずらした値となる。
・・・ところが、"0x7C00" の意味については、CPU関連を調べても何も分からない。ブートローダやMBR関連の情報を調べても、単に0x7C00にロードされる、と書かれているだけで、なぜこの値なのか?誰が決めたのか?についての情報は皆無にみえる。
前ぶりが長くなったが、本記事はMBRがロードされる "0x7C00" というアドレスの起源と、その意味について調べた結果をまとめている。
この記事単体で何かしら「使える」知識を増やすことは出来ないが、もしも読者のあなたが "0x7C00" について喉に魚の骨が刺さったままのような感触を覚えているのであれば、ぜひ一読をお奨めしたい。
アルゴリズムの観点から、プログラミングの奥深さと楽しさをコラムと練習問題で学べる。
ただし、メモリ効率や速度を強く意識したアルゴリズムが中心テーマとなるため、昨今広く使われているWebプログラミングとは全く異なる世界が広がっている点には注意すること。主にC言語で、ソートや探索など、最近のスクリプト言語であれば関数やメソッドを呼ぶだけで済ませることの出来る面倒な処理、その「裏側」の実装部分についての話になってくる。
2000年~2004年頃は、自分のPCや実家のPCについては自分がパーツを集めて組んだ自作PCを使っていた。
自分の方は、2004年にメーカー製のPCに買い換え、自分の自作PCについては処分が終わっていた。記憶がおぼろげだが、秋葉原の中古PC/パーツ買い取り店に持ち込んだところ、ケースも含めて値段が付かない分も引き取ってくれたので助かった記憶がある。
で、GW中は実家の家族が使っているPCをツクモの最新機種に入れ換えた。それに伴い色々整理していたら、今まで使っていたPCのさらにその前のPCが出てきた。こちらも自作PC。
というわけで、GW中はほぼ、二台の自作PCの処分で潰れてしまった。なにしろ実家が千葉県の田舎で、秋葉原までの往復が大変。というわけで習志野の自分のアパートまでまずクロネコヤマトで送った。
続いて習志野の自分のアパートに到着したPCを分解・清掃し、ドライバCDやMBの説明書などを整理し、一日一台のペースで秋葉原まで行き処分。しかしケースまでは値が付かず、今回持ち込んだ店では残念ながら引き取りはしておらず、アパートまで持ち帰ることになった。
残ったPCケースやMB(コンデンサーが破裂していて買い取り不可)については、幸いなことに不燃物としてゴミ出しできるサイズだったので、そのまま先日、不燃物として処分。
最後に残っていた、17インチCRTモニタについては処分業者に先日来て貰って処分。
自作PCの処分はホンッッッッッット、疲れるわ~~~・・・(;´Д`)
基本、PCはメーカー引き取りになるのだけれど、自作PCについては「一般社団法人 パソコン3R推進協会」や地元の回収業者に相談、ってことらしい。
こちらに頼んでも良かったのだけれど、代金の振り込みやゆうパックでの郵送など、数日以上タイムラグが発生してしまう。
今回はGW中に処分してしまいたかったので(アパート狭いしww)、秋葉原に持ち込んだり民間の処分業者にお願いしたりでドタバタしてしまった。
[OUT] PC/モニタ宅配料金総額 = \8,200 (概算) 秋葉原往復 \900 x 3回 = \2,700 パーツ整理・売却に要した作業時間 平均5h/day x 4 = 20h → 時給\800換算 = \16,000 17inchCRTモニタ処分費用 = \4,200 ---------------------------------- 合計 \31,100 [IN] パーツ売却代 \1,050 + \400 = \1,450 [IN] - [OUT] = -\29,650
OSで2世代以上前に組んだ自作PCを中古売却する時に何が面倒かというと、「値段が付かない/壊れている(今回のコンデンサー破裂MBのような)パーツ」を引き取ってくれるかどうかを調べ、引き取れない場合の処分まで考えないといけない点。
わざわざ秋葉原まで行かなくとも、郵送や宅配でお店まで送って見積もり・買い取りできる店も当然あるのだけれど、日数がかかるのと、引き取り不可で戻されてきたパーツの処分方法を考慮するひつようがある。
それを考えると・・・なるべく(アパートも狭いしww)即日で処分したいので、結局秋葉原まで直接持ち込み・・・という形になってしまうんだよなぁ。
とはいえ、これで古いPCも処分でき、気分的にスッキリできた。
牛肉・豚肉・鶏肉・乳製品などは普段通りに消費出来る。風説・流言飛語を原因とするパニックに注意し、まずは政府発表を確認すること。
不安に思われる場合は、まず農林水産省の口蹄疫対策ページを参照のこと。
消費者向けの「お肉や乳製品食べても大丈夫?」については下記ページ参照のこと。
こうした疾病対策イベントにおいては、消費者として以下のような情報は特に注意して取り扱いたい。
要するにプロパガンダに利用されやすいので注意しましょう、ということ。
恐怖心・不安感を特定の政権や特定の国に差し向けるような情報操作は、緊急度の高い疾病対策イベントにおいて効果を発揮する。冷静に検証する余裕が無ければ、とりあえずスルーしておきたい。
お肉や乳製品は通常通り購入・消費可能である事を把握し、パニックに陥らないことが重要。
外国からどう見えているか確認したい場合は以下のキーワードで検索:
"foot-and-mouth disease outbreak japan"
ヒトへの感染については以下のキーワードで検索:
"foot-and-mouth disease human infection"
なお "Hand, foot and mouth disease" というのが引っ掛かる場合があるが、こちらはヒトの乳幼児が罹る「手足口病」のことで、口蹄疫とは異なる。
フリーのを探しているが、サードパーティのリソースエディタとなると、有名どころは軒並みシェアウェアになっているようだ。
まぁぶっちゃけた話「ちゃんとVC++/VC#のStandard Edition買えよ」という事だろう。
参考:
※ "Resource Hacker"は古そうなので見送り。
フリーだと "XN Resource Editor" というのが見つかって、少し試してみたのだけれど・・・いろいろと挙動が怪しい所が多くて見送り。StringTableのリソースをちょこっと弄ってみただけだけれど、何だかIDが勝手に振り直されたり、文字列リソースの追加メニュー項目がずーっとdisableになってて、「これじゃ文字列テーブルにリソースを追加できないじゃん…?文字列テーブル単位で追加しろ、ということ?」という具合にクセが強い。
…クセが強い位までならまだ我慢が出来るが、さすがに我慢出来なくなったのが「保存したRESファイルを再読込すると(少なくとも文字列テーブルの)IDが全部初期化される」挙動。StringTableしか試してないので、他のリソースタイプがどうかは不明だが、放り出すのには充分な理由。
※version 3.0.0.1を使用
※上記挙動に関しては、「文字列リソース」に関する自分の無理解が原因でした。文字列リソースは、16個を一組としたテーブルブロックで管理され、テーブルブロックのIDは "先頭の文字列ID / 16 + 1" で自動的に振られます。そのため、自分が「おかしい」と感じていた挙動は、実は全て正しかったことになります。
Googleで検索すると上位に来るので、フリーと言うこともあり使ってる人も多いし何よりメニューなど日本語化パッチがあるので、便利そうではあるのだが・・・一般的な「アプリケーション開発」用途には使えないと判断。いやまぁ、そもそも".rc"ファイルすっとばしていきなり".res"ファイルやEXE/DLLの中身を操作するアプリケーションなので、VCのIDEをいずれStandard Editionにアップグレードしたい、なんていう人にはそもそも向いてない。EXEやDLLのローカライズには向いているのだろう。
幸いにも2010年現在、「これで必要最低限OK!」というフリーのリソースエディタが見つかった。
ちゃんと".rc"ファイルから作成してくれるのが嬉しい。"resource.h"も同時生成してくれるのでそのままVCのプロジェクトに組み込める。
日本語も対応しており、SJISで".rc"ファイルを作成してくれる。
簡単なダイアログ/メニューを作って、Win32APIの実験をする位であればこれで充分だろう。
※1.4.13-win32を使用
すみません、勘違いしてました(;´Д`)。
文字列リソースの場合、16個の文字列を一組の文字列テーブルとして管理しています。FindResource()やFindResourceEx()で文字列リソースを取り出そうとする場合は、その文字列リソースのIDではなくて、文字列リソースが格納されているテーブルのIDを指定する必要があります。16個で一組になっており、Resource Compilerにより「先頭の文字列リソースID / 16 + 1」というIDが自動的に振られます。
その内容も、16個の文字列リソースがバイナリで格納されている為、一つ一つを取り出すには専用の処理を組む必要があります。
詳しくは次の記事を参照して下さい。
これを理解せずに試行錯誤していたため、以下の内容は誤りを含んでおり、無視して下さい。
"String Table"リソースを追加し、"Neutral"と"日本語"、二つのテーブルで同じIDで異なる文字列を用意した後、
すると、一応UNICODE文字列(WCHAR)のデータが取得出来たのだが、中身はNeutralで指定した文字列になっている。
XN Resource Editorの問題か、そもそもリソースデータのバイナリ表現上の制限でうまく区別出来ないか。
とりあえず、「一つのリソースファイル内の文字列リソースで、同じリソースID+異なる言語」は止めておいた方が余計なトラップに嵌らなくて済みそう。
MAKELANGIDで日本語のIDを作成し、FindResourceEx()で文字列リソースを取得するサンプル:
#include <windows.h> #include <stdio.h> void PrintErrorMsg(DWORD err) { LPTSTR lpMsgBuf; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); printf("%s\n", lpMsgBuf); LocalFree(lpMsgBuf); } int main(int argc, char *argv[]) { HINSTANCE hCurrentInst; HRSRC hResRc; HGLOBAL hGlobal; DWORD dwSizeofRes; char *buf = NULL; hCurrentInst = GetModuleHandle(NULL); hResRc = FindResourceEx( hCurrentInst, RT_STRING, // NG : 16個一組の文字列テーブルのブロックIDを指定する。 // ブロックIDは、"(そのブロック中の適当な文字列ID) / 16 + 1" MAKEINTRESOURCE(1), // →正しくは MAKEINTRESOUCE( 1/16 + 1) (今回は偶々結果として同じ"1"になっただけ) MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN) ); if (NULL == hResRc) { PrintErrorMsg(GetLastError()); return -1; } dwSizeofRes = SizeofResource(hCurrentInst, hResRc); if (0 == dwSizeofRes) { PrintErrorMsg(GetLastError()); return -2; } printf("size = %d\n", dwSizeofRes); hGlobal = LoadResource(hCurrentInst, hResRc); if (NULL == hGlobal) { PrintErrorMsg(GetLastError()); return -3; } buf = (char*)LockResource(hGlobal); if (NULL == buf) { PrintErrorMsg(GetLastError()); return -4; } // NG:取得されるのは16個の文字列を一組にした文字列テーブルの「ブロック」データ。 printf("string resource : [%s]\n", buf); return 0; }
※なお、最後のprintf()は上手く動きません。本来ならtchar.hをincludeしてUNICODE対応させる必要があります。(参考: C言語系/memos/VC++/03, UNICODE対応とtchar.h)
じゃぁどうやって中身を確認したの?ですが・・・OllyDbgで確認(爆)。
基本的にWikipediaからの抜き書き、自分用のまとめメモです。
単純に、Wikipediaのページをあっち行ったりこっち行ったりするのが面倒くさいのでまとめてます。
Linuxで"VESA対応のビデオカード云々"って話題に挙がったりしませんか?
VGAとVESAは規格としては独立している。Windows95発売時点ではVESAはまだリアルモードしかサポートしていなかった。プロテクトモードで動作するWindows95/NTに対応する為、ビデオカード各社は独自のデバイスドライバを開発することになった。
Wikipediaショートカット:
他: