タイトル/名前 | 更新者 | 更新日 |
---|---|---|
C言語系/呼び出し規約/x86/syscall | msakamoto-sf | 2010-03-19 16:48:39 |
C言語系/呼び出し規約/x86/safecall | msakamoto-sf | 2010-03-19 16:35:44 |
C言語系/memos/VC++/01, 共通系コンパイルオプション | msakamoto-sf | 2010-03-17 11:49:26 |
Assembler/なぜx86ではMBRが"0x7C00"にロードされるのか? | msakamoto-sf | 2010-03-16 13:10:26 |
日記/2010/03/15/7C00の記事を近日公開 | msakamoto-sf | 2010-03-15 23:29:56 |
日記/2010/03/12/86-DOSの時点ではMBRは200Hにロード | msakamoto-sf | 2010-03-12 16:43:29 |
日記/2010/03/11/まだ0x7C00の謎が解けていない。 | msakamoto-sf | 2010-03-11 18:36:19 |
Assembler | msakamoto-sf | 2010-03-09 22:58:12 |
日記/2010/03/08/FreePWING, wikipedia-fpwでWikipedia-jaのデータを変換 | msakamoto-sf | 2010-03-08 18:29:47 |
日記/2010/03/07/「銀の弾丸」が無くても狼男を倒せる世界へ | msakamoto-sf | 2010-03-08 01:45:33 |
sysycall呼び出し規約は、OS/2 の 32bit API で使われていた。
Linux/BSDでのsyscall(2)とは無関係。
2010年の時点のMSDNによると、現在は "__syscall" 呼び出し規約はサポートされていない。(obsoleted)
OpenWatcom 1.8 においては、現在もサポートされている。(2010年3月時点)
OpenWatcom 1.8 User's manual より:
The __syscall keyword may be used with function definitions, and indicates that the calling convention used is compatible with functions provided by 32-bit OS/2.
Notes:
DelphiにおいてCOM/OLEプログラミングで使う。タイプライブラリとも関連してくる。
詳細は以下のEMBARCADERO, RAD Studio のWikiページを参照。
その他:
"Hello, World!"レベルの単純なプログラムを題材に、基本的なコンパイルオプションのまとめ。
対象:Visual C++ 2008 Express Edition
> cl Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. > link Microsoft (R) Incremental Linker Version 9.00.30729.01 Copyright (C) Microsoft Corporation. All rights reserved.
ここではコンソール/GUI/DLLに関わらず共通して使われそうなオプションをまとめてみた。
重要:本記事で調査不足で曖昧だった点を解決した完全版をUPしました。ぜひこちらの方を参照して下さい。
x86アーキテクチャで、ブートローダ周りを調べ始めると必ず、
0x7C00
というマジックナンバーに遭遇する。"セグメント:オフセット"形式で
07C0:0000
という表記も見かける。
これはフロッピーディスク又はHDDのMBRが展開されるアドレスで、ブートローダ(MBRにインストールされる)はこのアドレスから始まることを想定して作成される。
一体誰がこのマジックナンバーを決定したのか?その起源と、確かな証拠を探してみた。
x86アーキテクチャのPCの原型であるIBM PC 5150 (1981年発表) の BIOS は、ディスケット(フロッピーディスク)の先頭セクタ1つ分(今のMBR)を 0x7C00 にロードし、ブートローダとして実行するよう作成されていた。これが起源と思われる。
以降のIBM PC(およびその互換機)もその仕様を維持し、結果としてPC/AT互換機およびその上で動作するBIOSに引き継がれていった。
"IBM Personal Computer XT Technical Reference manual" (*1) の Appendix-A に BIOS の全ソースコード(アセンブラ)が記載されている。
大雑把な流れ:
1142行目から "DISKETTE ATTACHMENT TEST" が始まり、この中で"INT 19h"が実行される。
1151行目の
F9:
ラベルからチェックが始まり、途中からPRINTERやRS232のチェックも始まる。
うまくいけば、1306 - 1307行の
1306: F21: ; LOAD_BOOT_STRAP: 1307: INT 19H ; GO TO THE BOOT LOADER
で "INT 19h" が実行される。
ディスケットからトラック0, セクタ0番を 0x7C00 上に読み込む。
まず 0x7C00 というマジックナンバーは、63, 64行目で定義されている。
63: ORG 7C00H 64: BOOT_LOCN LABEL FAR
INT 19hの割り込みハンドラは1417行目から始まり、その中で上のBOOT_LOCNを使ってブートローダを読み込んでいる。(ソースコード上は"BOOTSTRAP"という表記もあるが、とりあえずこの記事の日本語中では「ブートローダ」に統一しておく)
以下に該当コードを載せるが、"H1:"ラベルで始まるブロックで最初のセクタを0x7C00にロードし、成功すれば"H4:"ラベルでBOOT_LOCN、つまり0x7C00にJMPしている。
1417: ASSUME CS:CODE,DS:AB50 1418: ORG 0E6F2H 1419: 1420: BOOT_STRAP PROC NEAR 1421: STI ; ENABLE INTERRUPTS 1422: SUB AX,AX ; ESTABLISH ADDRESSING 1423: MOV DS,AX 1424: 1425: ;--- RESET THE DISK PARAMETER TABLE VECTOR 1426: 1427: MOV WORD PTR DISK_POINTER, OFFSET DISK_BASE 1428: MOV WORD PTR DISK_POINTER + 2, CS 1429: 1430: ; --- LOAD SYSTEM FROM DISKETTE -- CX HAS RETRY COUNT 1431: 1432: MOV CX,4 ; SET RETRY COUNT 1433: H1: ; IPL_SYSTEM 1434: PUSH CX ; SAVE RETRY COUNT 1435: MOV AH, 0 ; RESET THE DISKETTE SYSTEM 1436: INT 13H ; DISKETTE_IO 1437: JC H2 ; IF ERROR, TRY AGAIN 1438: MOV AX, 201H ; READ IN THE SINGLE SECTOR 1439: SUB DX, DX ; TO THE BOOT LOCATION 1440: MOV ES,DX 1441: MOV BX,OFFSET BOOT_LOCN 1442: ; DRIVE 0, HEAD 0 1443: MOV CX, 1 ; SECTOR 1, TRACK 0 1444: INT 13H ; DISKETTE_IO 1445: H2: 1446: POP CX ; RECOVER RETRY COUNT 1447: JNC H4 ; CF SET BY UNSUCCESSFUL 1448: LOOP H1 ; DO IT FOR RETRY TIMES 1449: 1450: ;----- UNABLE TO IPL FROM THE DISKETTE 1451: 1452: H3: 1453: INT 18H ; GOTO RESIDENT BASIC 1454: ;---- IPL HAS SUCCESSFUL 1455: 1456: H4: 1457: JMP BOOT_LOCN 1458: BOOT_STRAP ENDP
他にBIOSのソースを確認出来たのは同マニュアルの改訂版、およびPC-JrのTechnical Reference manualの二つ。
細かい違いはあるが、INT 19h で 0x7C00 以降にブートローダをロード成功後JMPする、という流れは全て同じだった。
86-DOSがなぜディスクの先頭セクタを200Hにロードするのか、なぜIBM PC 5150のROM BIOSおよび現在に至る互換BIOSがMBRを7C00Hにロードするのか、その値の意味は何か。
一通り謎が解けたので、現在まとめ記事を書いてます。今週中に公開予定。
それにしても当時のアセンブラって・・・現在とは少し違います。
86-DOSのコードで頻出していて、悩まされたのが
UP
と
PUT 100H
の二つ。
UPは現在の"CLD"のことでした。(シミュレータ上で86-DOSのMonitorコードをステップ実行してて、シミュレータの逆アセンブリ結果を見て初めて理解)
PUTの方は擬似コードなのですが、正直よく分からないです。ORGも併用されてるので、そのコードがどこのメモリに展開されるのか分かりづらい。
86-DOSのMonitorやbootstrapって、割り込みベクタが調整される前に動作するコード・・・つまり、キーボード入力やディスクI/Oを、I/Oポートの読み書きを駆使し、割り込みは一切使わずに書かれている・・・スゲー。
こういうのを目の当たりにすると、つくづく「たった四半世紀でここまで変わるものなのか・・・」と感心というかあっけにとられます。これからの25年、50年はどうなっちゃうんでしょうね。
IBM PC(5150)には、Microsoftが開発したPC-DOS(MS-DOS)が搭載されたが、その前身はSeattle Computer Products の Tim Paterson が開発した 86-DOS だった。
86-DOSはCP/Mの8086対応版が中々リリースされないため、Tim Paterson がとにもかくにもで開発したOSで、当初は"QDOS"(Quick and Dirty Operating System)とも呼ばれていた。
86-DOSのPDFマニュアルが現在も入手可能で、"86-DOS Programmers Manual"の"BOOTSTRAP LOADER LISTING"に、BOOTSTRAP用のコードが載っている。
これを見ると、200Hに最初のセクタがロードされ、そこにJMPするようになっている。
ようやくここで、"7C00H"が最初に現れたのが IBM PC 5150 のROM BIOS INT 19hであることが判明した。
(もちろん、それ以前のコンピュータシステムで、偶々 7C00 が使われていた可能性も否めない。しかし、現在のx86ベースPCの歴史の中で初めて出てきたのは、5150のROM BIOSで確定して良いだろう)
いよいよパズルのピースが残り一つ、になってきた。
IBM PC 5150 のROM BIOS自体は IBM の David Bradley が開発した。同氏は有名な"Alt-Ctrl-Del"キーコンビネーションをBIOSで導入した人物としても知られている。
最後のピース、7C00Hというアドレスを決定したのはDavid Bradleyなのか?なぜそのアドレスにしたのか?は同氏に質問してみるしかない。
特に、5150の最小メモリモデルは16KBのRAMしか搭載していない。ROM BIOSは固定で高位アドレスに割り当てられるので関係ないとしても、7C00H(=32KB - 1024B)へMBRをロードしようとしてもアクセス出来ない筈である。
少なくとも割り込みベクタを確保する為、最小の16KBはアドレス0から割り当てられる。つまり32KB - 1024Bにはどう頑張っても届かない筈。(16KBの場合はMAXで3FFFHまで)
あと少しで"0x7C00"の謎が解ける・・・と良いなあ。
Assembler/なぜx86ではMBRが"0x7C00"にロードされるのか?
で「ようやく0x7C00の起源が分かった」・・・と力を抜きかけたけど、よくよく考えたら
5160では0x7C00が使われている
のが判明しただけで、
5150「から」0x7C00が使われている
のは未だに不明のまま。
本当に証明したいなら、「ここまでは0x7C00が使われて居らず、この時点から0x7C00が使われ始めた」という境界線を見つけないといけない。
それともう一つ、0x7C00の値の意味も未だに不明。ちょうど32KB、0x8000から1024バイト分(=512バイトx2)マイナスされたのが0x7C00になるが、なぜわざわざこのアドレスになったのか?どういう意味があるのか?
CP/Mまで手を広げて探索中。そもそも、IBMはPC-5150のOSとしてDigital Research社のCP/Mを狙っていた。
ROM BASICはMicrosoftが開発し、結局OSもMicrosoftが開発している。ただしOSについては、Digital Research社によるCP/Mの8086対応の遅れにしびれを切らしたSCPが、Tim Paterson作成の86-DOS (QDOS)を1980年に発表する。で、これをビル・ゲイツが買い取ってIBM PCに載せた。
ということはMS-DOSの源は86-DOSということになり、さらにその基本的な設計はCP/Mまで遡ることになる。
CP/Mでは"BIOS"という概念がOSの中に取り込まれていた。
・・・ということは、86-DOSの中にもBIOSに相当する部分があったのだろうか?ROM BASICも、OSもMicrosoftが作っている。当然、ROM BASICを起動する為のインターフェイス、INT 18h 割り込みの部分もMicrosoftが絡んでいて間違いなさそう。ということは・・・もしかして、ROM BIOSもMicrosoft製なのかな?86-DOSからBIOSに相当する部分を抽出し、BASICからもDOSからも呼べるように整えられる・・・という非常に自然な流れに思える。
知り合いからWikipedia-jaのデータを、辞書ソフトで使われる JIS X 4081 形式に変換出来ないかと頼まれた。
変換ツールは存在するのだが、プログラマではないその知り合いでは、自分で試すには難易度が高すぎるらしい。
TDDに対してのスタンスを自分の中ではっきりさせたい為、前から気になっていた書籍を読み込んでみた。
TDDやアジャイルに対してのスタンスが、ようやく自分の中で焦点を結んだ。
「現場でTDDを使おう/XPで行こうと言われたら、そう願う人達の静かな味方になる。」
それが、自分なりの結論だ。
アジャイル/TDD/XPを導入しようとしまいと、プロジェクトとそれを推進する人間の集団を特定の方向に引っ張って行くには、信念と自信をもった実力に裏打ちされたリーダーが必要なのだ。
そんな極々当たり前のことすら自分は分かっちゃいなかった。自分で信じ切れない言葉は、どう言い回しを変えたところで他人が信じる筈はない。
もし今後携わる開発現場で、リーダーやマネージャなどが「アジャイル/XP/TDDを使います!」と宣言したときに少しでも学習負荷を下げるべく、座学で予習しておく。それが今の自分に出来ることだろうし、今後もそれが限界だろう。
そうした現場に出会ったら、できるかぎり、そのリーダーやマネージャを補佐する事にしよう。「アジャイル/XP/TDDをうまく導入して少しでも開発現場を改善したい」と願う人達の、開発者としての最初の味方になろう。
今回読んだ本の中から、特に胸を打たれたセンテンスを引用して終わりにする。
・「闘うプログラマー」p12:
最後には、優れた作品は愛情と暴力によって創造されるのだと知った。
・「プログラマーのジレンマ」p350:
「手法の本当の目的は、誰かの問題を解決することではなく、本を売ることだ」
(...)
「手法の大きな問題は、手法を開発するような頭のいい人たちが実践すれば、うまくいくことだ。
言われたことに従うほかは何もしようとしない鈍感人間が実践しても、うまくいかない。
いずれにせよ、開発者の大半はソフトウェア開発の本も読まず、ソフトウェア開発に関するウェブサイトも読まず、
スラッシュドットすら読まない。だから、われわれがいくら書き続けても、彼らの耳には届かない。
(...)
・「プログラマーのジレンマ」p409:
(全て表示する)クヌースは、TeXとメタフォントを開発したことで、ビル・ジョイとは正反対の結論に達した。
ソフトウェアを書くことは、本を書くより「はるかに難しい」。