home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 2001 June / VPR0106A.BIN / OLS / NWSA140 / nwsa140.lzh / NWSA.TXT < prev    next >
Text File  |  2001-03-04  |  40KB  |  855 lines

  1.                       NOWSMART ASSEMBLER
  2.                                           Version 1.40
  3.  
  4.                                            2001年03月04日
  5.                                             NOWSMARTSOFT
  6.  
  7.  
  8. 【基本仕様】
  9.  
  10. 分野            開発言語
  11.  
  12. 機能            MASM 準拠のアセンブラ
  13.  
  14. 対応CPU命令     8086,80186,80286,80386,80486,Pentium,PentiumProまでの全命令
  15.                 MMX命令(マルチメディア・エクステンション命令)
  16.                 AMD 社の3DNow! 命令(Athlon,Duron 等)
  17.  
  18. 擬似命令の仕様  MASM 準拠
  19.  
  20. ファイル名      NWSA.EXE
  21.  
  22. 動作環境        Windows 95/98/Me/NT/2000
  23.  
  24. 他に必要なもの  Visual C++,Borland C++,Microsoft C++ などのリンカ
  25.  
  26. 実行形態        32 BIT コンソールアプリケーション
  27.  
  28. 取り扱い        完全フリーソフト
  29.  
  30.  
  31. 【注意事項】
  32.  
  33.  同梱されているのはアセンブラのみで、リンカはなく、ソースファイルからオブジェクトファイルを作成する機能しかありません。
  34.  
  35.  このアセンブラは、Windows の 32 BIT コンソールプログラムですので、DOS 上では実行できません。
  36.  
  37.  通常は、Visual C++ と共に使用してください。
  38.  
  39. 【Install 方法】
  40.  
  41. インストール方法は特にありません。
  42.  
  43. nwsa.exe がアセンブラ本体であり、コマンドラインから使用したいときは、これにパスが通るようにするだけです。
  44.  
  45. Visual C++ だけから使用し、コマンドラインから使用する予定が無い場合は、nwsa.exe を任意のフォルダに置いておいて構いません。
  46.  
  47.  
  48. 【Visual C++ の設定】
  49.  
  50. このアセンブラを Visual C++ で使用したい場合、次のように設定します。
  51.  
  52.  
  53. 1. ワークスペースダイアログの FileView タブを表示させ、対象のプロジェクトのSource Files を右クリックします。
  54.  
  55. 2. 出てきたポップアップメニューの”ファイルをフォルダへ追加”をクリックし、”プロジェクトへファイルを追加”のダイアログを出します。
  56.  
  57. 3. このダイアログで既存のアセンブラのソースファイルを選択するか、または新規に作成したいソースファイル名を入力します。新規に作成する場合は、確認のダイアログボックスが表示されます。
  58.  
  59. 4. FileView に上記で入力したソースファイル名が表示されていることを確認します。
  60.  
  61. 5. そのソースファイル名を右クリックし、ポップアップメニューの”設定”をクリックします。
  62.  
  63. 6. 出てきた”プロジェクトの設定”ダイアログの”カスタムビルド”タブが選択されていることを確認します。
  64.  
  65. 7.”コマンド”の欄に例えば次のように入力します。
  66.     c:\????????\nwsa -Zd -coff -Fo$(OutDir)\$(InputName).obj $(InputPath)
  67.     ~~~~~~~~~~~
  68.     下線の部分には nwsa.exe を置いてあるディレクトリ名を指定します。
  69.  
  70. 8.同様に出力欄に、
  71.     $(OutDir)\$(InputName).obj
  72.     と入力します。
  73.  
  74. 9.アセンブラソースファイルが複数ある場合は同様の作業を繰り返します。
  75.  
  76.  
  77. 上記の設定で、通常の様にビルド作業を行うと自動的に指定したソースファイルがアセンブルされ、CやC++のプログラムとリンクされてEXE形式が出来上がります。
  78.  
  79.  
  80. 【コマンドラインオプション】
  81.  
  82.  コマンドラインからパラメータなしで nwsa.exe を実行すると次のようなヘルプメッセージが出力されます。
  83.  
  84. NOWSMART ASSEMBLER Version 1.10 COPYRIGHT (C) NOWSMARTSOFT 2001
  85.  
  86. syntax : nwsa <paras>
  87. func   : assemble specified source files.
  88. <paras>::={ -<opt> | /<opt> | <sourcefile> | @<configfile> }
  89. <opt>::=
  90. l         [generate list file] |
  91. fo<file>  [change object filename] |
  92. fl<file>  [change list filename] |
  93. jo        [optimize jump] |
  94. pl        [use local label within procedure] |
  95. coff      [output a coff object] |
  96. zd        [bury linenumber information for debug]
  97.  
  98.  
  99. コマンドラインオプションは次の通りです。
  100. -l              リストファイルを出力します。デフォルトのファイル名は *.lst です。
  101.  
  102. -fo<file>       オブジェクトファイル名を変更します。デフォルトのファイル名は *.obj です。
  103.  
  104. -fl<file>       リストファイルのファイル名を変更します。デフォルトのファイル名は *.lst です。
  105.  
  106. -jo             jmp 命令を最適化し、1バイトで飛べる範囲の near ラベルへは short jmp を使用します。
  107.  
  108. -pl             プロシージャ内部(proc~endp)でlabel名: で定義されたラベルをプロシージャ内部のロー
  109.                 カルラベルにします。
  110.  
  111. -coff           obj ファイルを COFF 形式にします。デフォルトでは OMF 形式です。
  112.  
  113. -zd             デバッグ用に関数情報と行番号情報を埋め込みます。現在は COFF 形式のみに対応します。
  114.  
  115.  
  116. オプションは、- と / のいずれでも構いません。
  117.  
  118.  
  119.  複数のソースファイルを指定することが出来ます。その場合それらのファイルを連結したファイルをアセンブルしたのと同じ結果が出力されます。
  120.  
  121.  
  122.  コマンドラインが長くなる場合は、その内容をコンフィギュレーションファイルに記述して、@ConfigFilename の様に指定します。コンフィギュレーションファイル中では、スペースの変わりに改行でオプションやファイル名を区切ります。; の後ろにコメントを記述することも出来ます。
  123.  
  124. 例:
  125.  
  126. abc.cfg
  127. -l               ;リストファイルを出力する。
  128. -jo              ;short jmp を自動的に生成する。
  129. -pl              ;プロシージャ内の : ラベルをローカルラベルにする。
  130. -coff            ;COFF 形式で出力する。
  131. -zd              ;デバッグ情報を出力する。
  132. Test.asm         ;アセンブラソースファイル
  133.  
  134. コマンドライン  nwsa @abc.cfg
  135.  
  136.  
  137.  なお、オプションに関しては、コンフィギュレーションファイル中のものよりもコマンドラインで指定したものの方が優先されます。相反するものでない限り、合成した結果となります。
  138.  
  139.  明示的にコンフィギュレーションファイルを指定しないと、nwsa.cfg というファイルが自動的にコンフィギュレーションファイルとして使用されます。nwsa.cfg の中には通常はオプションだけを記述し、ファイル名はコマンドラインから指定するようにします。
  140.  
  141.  
  142. 【サンプルコード1】
  143.  
  144. Visual C++ から、nwsa を使用する際にポイントとなる点について例を使って説明します。
  145.  
  146.  まず、C++ 言語とアセンブラとの間で関数名や変数名の受け渡しをするために、C++言語のソース側では、ソースファイルの先頭などで次のように、extern "C" { } を記述します。
  147.  
  148. extern "C" {
  149.       int   _cdecl AsmAdd( int Para1, int Para2 );
  150. }
  151.  
  152. 純粋なC言語ではこのextern "C" { と } の部分は必要なく、単に、
  153.  
  154. int   _cdecl AsmAdd( int Para1, int Para2 );
  155.  
  156. で構いません。
  157.  
  158. この例では、AsmAdd() という関数をアセンブラで記述するものとします。AsmAdd()関数は、int 型の二つの引数を持ち、それらの和をint型で返すような関数です。
  159.  
  160. C++言語やC言語のソースでは、この関数を使用したい箇所で通常の関数呼び出しを行います。例えば、
  161.  
  162.         int     Sum;
  163.         Sum     = AsmAdd( 100, 200 );
  164.  
  165. という具合です。この例では、100 と 200 という整数値をアセンブラの関数 AsmAdd() に渡し、その関数が返した結果を Sum に入れようとしています。当然のことながら、100+200=300 という数値が Sum に入ることを期待しています。
  166.  
  167. 次にアセンブラのソースファイルの記述について説明します。アセンブラソースファイルは通常、拡張子を asm にして作成します。nwsa では、拡張子を省略したファイルネームをパラメータとして渡すと、自動的に asm という拡張子を付加したファイルをアセンブルしようとします。もし、拡張子が無いファイルをアセンブルしたい場合は、ファイル名の最後に"."(ピリオド、ドット)を付加してパラメータに渡して下さい。
  168. この例では、アセンブラソースファイルの中身は次のようになります。
  169.  
  170.                 .386
  171.                 .model  small, c
  172.  
  173. _text           segment para use32
  174.  
  175. AsmAdd          proc    near
  176.                 arg     Para1:dword, Para2:dword
  177.                 
  178.                 mov     eax,Para1
  179.                 add     eax,Para2
  180.                 
  181.                 ret
  182.                 
  183. AsmAdd          endp
  184.                 
  185. _text           ends
  186.                 
  187.                 end
  188.  
  189. 最初の行の .386 という擬似命令は、80386 以降の CPU の命令を使用許可するものです。これを指定することで、32 BIT レジスタが使用できるようになるほか、80386で新しく付け加わった命令が使用できるようになります。今回のケースでも、32 BIT のeax レジスタを使用しますので必要です。ここで、386 以上の命令も使用許可する場合には、.486や.Pentium,.PentiumPro などを使用することも出来ます。一般に、80486 以降と、80386 以前ではそれほど大幅な変更点は無いと考えられていますが、80486 ではキャッシュ制御命令のほか、整数命令などでも重要な命令が追加されています。Pentium や PentiumPro でも、使いこなせば重要な命令の追加があります。また、MMX 命令も許可する場合は、.MMX を指定します。AMD の Athlon 等では 3DNow! 命令が追加されていますが、それらの命令を使用する際には、.3DNow を指定します。
  190.  
  191.  次の行の、.model 擬似命令は、メモリモデルと、アセンブラと共に使用する高級言語の種類を指定します。nwsa では、現在C言語呼び出しにしか正式には対応していません。また、メモリモデルというのは、16 BIT プログラムを作る場合以外には関係ありません。またメモリモデルを指定しても、簡易セグメント擬似命令を使用しなければ何の効果もありません。今回の場合、smallの部分がメモリモデルを指定していますが、他に、large,compact,medium,huge 等が指定できますが、Windows 95/98/Me/NT/2000 用のプログラムを作る際にはほとんど関係ありません。必ず small を指定すると考えてください。この指定は、PROC 擬似命令でnearやfar指定を省略した場合などに影響を与えますが、省略しない場合は意味を持ちません。最近の MASM では、FLAT という指定も出来るようですが、nwsa ではまだ対応していません。カンマで区切られた第二パラメータの c の部分が高級言語の種類を表しています。これで、C言語のインターフェースを使用することを宣言しています。C言語のデフォルトの呼び出しに対応しています。C言語では、一般に、_cdecl 呼び出しと、_stdcall 呼び出しの二つが使用されます。何も指定しなければ、_cdecl 呼び出しになりますが、先の例では、念のため関数のプロトタイプ宣言で、_cdecl キーワードで関数を修飾し、そのことを明示していました。_cdecl 呼び出しは、スタックの管理を全て呼び出し側が行う方式です。例えば、2つのDWORDパラメータをスタックにpushした場合には、責任を持って2*4=8 バイト分のスタックの除去を呼び出し側が行います。この方式は可変長の引数を呼び出し側がpushした場合に呼び出された側がスタックの管理をミスするのを防ぐ働きがあり安全性が高い方法です。一方、_stdcall 呼び出しでは、呼び出された側がスタックの除去を行います。この方式の利点はスタックを除去するコードの量を減らせることにあります。ただし、呼び出し元の push したスタックの量と呼び出された側がスタックポインタを add する量とが完全に一致していなければならず、注意が必要です。Windows API は、基本的に _stdcall 呼び出しを使用しています。
  192.  
  193.  さらに次の行の、_text segment para use32 は、セグメント擬似命令です。この命令はend文の直前の _text ends 命令と対応し、この間に囲まれた部分のコードを指定したセグメントに収めることを指示する命令です。para は、セグメントの先頭アドレスのアラインメントを指定していますが、通常は気にしないで下さい。use32 は、このセグメントが 32 BIT セグメントであることを示します。他に use16 というものがありますがこちらは 16 BIT セグメントであることを示します。このUSE指定は非常に重要で、現在のWindows では特殊な場合を除いて必ず USE32 を指定する必要があります。32 BIT セグメントと 16 BIT セグメントは、386 系のセグメントディスクリプタによって完全に区別されます。32 BIT セグメント内部の命令では、デフォルトで 32 BIT 幅のデータ転送を行い、アドレス計算も 32 BIT で行われます。レジスタも EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP,EIP
  194. が使用されます。逆に 16 BIT セグメント内部ではデフォルトでデータ幅が16 BIT、アドレス計算も 16 BIT で行われます。ただし、いずれの場合でも命令の先頭にプリフィクスバイトというものを付加することでデフォルトの指定を反転させることが可能です。バス幅に関連したプリフィクスバイトには2種類有り、データ転送の幅を反転するものと、アドレス計算の幅を反転するものとがあります。これらのプリフィクスはアセンブラによって自動的に挿入されますので、nwsa を使用するユーザーは普段は何も気にする必要はありません。ただし、USE32の指定がなぜ重要かは知っておいてください。例えば、USE32 指定のセグメント内でeax レジスタを使用する命令を書いた時には、データ幅反転プリフィクスは付きません。ところが、USE32 指定のセグメント内でax レジスタを使用する命令を書いた場合は自動的にデータ幅反転プリフィクスが付加されます。現在の32BIT- Windows ではこのセグメントは正しく実行されます。ところが、仮にこのコードが実際には、16 BIT のセグメントで走行した場合には、eax を使うはずの命令が ax を使い、ax を使うはずの命令が eax を使用してしまいます。つまり、USE32 を指定した論理セグメントは、実行段階でも 32 BIT セグメントで実行されなければならないのです。アドレス幅変更プリフィクスの場合も全く同様なことが起こります。重要なことは細部を理解することではなく、今言ったようなUSE32 指定の概略的な意味を知っておくことです。
  195.  
  196.  次に、AsmAdd関数本体の宣言に入ります。最初の行では、AsmAdd proc nearと書かれていますが、これがこの関数の入り口を示すものです、これは、後の方の AsmAdd endp と対応しており、これらの間に囲まれた部分がAsmAdd関数であることを示しています。
  197. near というキーワードは、この関数を call 命令で呼び出すとき、near コールを使用し、かつ、関数内部で書かれた ret 命令が near return(retn) にコード化されることを指定します。現在の 32 BIT - Windows では、ユーザープログラムで far コールを使用する利点はまず有りませんので、必ず near を指定するようにしてください。far を指定した場合、現在の Visual C++ 環境で何が生じるかは保証できません。恐らくリンク段階で何かのエラーになるか、リンクがうまくいったとしても実行段階で一般保護例外などが生じる可能性が高いです。また、nwsa 自体も far コールや far ジャンプに関しては保証いたしません。そもそもCOFF 形式も far コールやfarジャンプに対応していません。また、この proc擬似命令は、AsmAdd というラベルをグローバル名前空間に登録し、アセンブラソースファイルの任意の位置から参照できるようにし、かつ、public 指定します。public 指定とは、シンボルをリンク段階で他のオブジェクトから参照できるようにすることです。つまり、AsmAdd というラベルは、Visual C++ の中の他のC++のソースファイルから参照できる様になります。次の行の arg 擬似命令は、_cdecl 呼び出しまたは、_stdcall 呼び出しの引数をアセンブラから簡単に使用できるようにするための命令です。この例では、Para1 と Para2 という二つの DWORD(32BIT)型の引数を取ることを示しています。arg 擬似命令で指定した引数名は、指定した型を持ったラベルとして登録されます。今の例では、Para1 や Para2 自体が、DWORD 型を持っています。例の様に、mov 命令や、add 命令のオペランドに自由に使用することが出来ます。内部的には、スタックフレームを作成して、ss:[ebp+?]の形式でスタック上のメモリ内容を参照するようなコードが自動的に作成されます。このようにして、次の行の mov eax,Para1 は、第一引数の内容を eax に代入します。その次の行の add eax,Para2 は、第二引数の内容を eax に加算します。そして最後に、ret 命令が書かれていますが、この命令は、自動的に複合的な命令を埋め込みます。今の場合、スタックフレームを除去するための pop ebp 命令と、near リターン命令である、retn です。これが、near リターン命令になるのは、この関数が、proc near としてnear宣言されているためです。proc far としている場合は、retf 命令が吐き出されます。なお、ソースレベルで、retn や retf を明示的に指定することも可能です。その場合はその指示に従った命令を埋め込みます。ただし、retn や retf もやはり自動的にスタックフレームの除去のために pop ebp 命令が埋め込まれることになります。
  198.  なお、int 型を戻り値に持つ関数では、戻り値は eax レジスタに入れて戻ってきます。今の例でも、eax レジスタに入った計算結果が、C(C++)言語に受け渡されることになります。
  199.  
  200.  なお、最後の行の end 命令は特に必要ありませんが、書いておくと、それ以後の行がアセンブルされなくなります。この後には任意のコメントを入れることも可能です。
  201.  
  202.  
  203. 【サンプルコード2】
  204.  
  205. アセンブラから Windows API を直接呼び出す方法について説明します。
  206.  
  207. 通常のWindows API は、_stdcall 呼び出しです。_stdcall 呼び出しは、呼び出し側が pushしたスタック引数を、呼び出された関数内部で除去して戻ってくるような呼び出し規約です。_stdcall 呼び出しはスタック除去コードを呼び出し側に持つ必要が無いためにコードサイズの節約にはなる反面、呼び出し側と呼び出された側のスタックサイズの仮定のミスマッチがあると、大変危険な方式です。そこで、Windows では、内部的には高級言語から見える関数名の後に @ マークに続けて除去するスタックサイズを10 進数表記で記したものが実際のラベル名として宣言されています。
  208.  
  209. 例えば、簡単な Windows API として、Sleep() 関数を取り上げます。この関数の働きは(ms)単位で指定した時間だけ制御を Windows に返し、関数を呼び出した側はその時間だけ実行を停止するものです。この関数のプロトタイプ宣言は、次の通りです。
  210.  
  211. void WINAPI     Sleep(DWORD dwMilliseconds);
  212.  
  213. また、他の場所で WINAPI は次のようにマクロ定義されています。
  214. #define WINAPI     __stdcall
  215.  
  216. よって説明したとおり、Sleep() API は、_stdcall 呼び出し規約に従った関数です。実際には、DLL になっていますが、とりあえず、DLL であることは気にする必要はありません。
  217.  
  218.  プロトタイプ宣言から分かるように、この関数はDWORD 型の引数を一つだけとりますから、自動除去するスタックのサイズは4です。よって実際のラベル名は、Sleep@4 となります。よって、Sleep() API を nwsa のアセンブルソースコードから呼び出すには、次のようにします。
  219.  
  220.                 .386
  221.                 .model  small, c
  222.  
  223.                 extrn   Sleep@4:near
  224.  
  225. _text           segment    para use32
  226.  
  227. TestAPI         proc    near
  228.                 
  229.                 push    dword ptr 1000
  230.                 call    Sleep@4
  231.                 
  232.                 ret
  233.                 
  234. TestAPI         endp
  235.                 
  236. _text           ends
  237.  
  238.         end
  239.  
  240.  
  241. まず、Sleep@4 ラベルを関数として登録するために、:near を指定して extrn 宣言します。
  242. 次に、TestAPI 関数の内部で、1000 という DWORD 値をスタックにpush した後、
  243. call 文で Sleep@4 関数を呼び出します。スタックの除去は、_stdcall 規約に従い、Sleep@4 関数が行いますから、こちらでは何もする必要はなく、call 関数から戻ってくると既に、push する前のスタックポインタに戻されています。したがって、ここで、ret 文を書けば、TestAPI 関数は正しく呼び出し元へ戻れます。
  244.  
  245.  
  246.  なお、スタックに push される際、引数の型が、BYTE型(つまりchar)やWORD型(つまりshort)の場合は、規約上、全て、4バイトのDWORD 型 に“切り上げ”が行われます。したがって、スタックから除去される量も1や2ではなく4になることに注意してください。
  247.  
  248.  複数の引数がある場合はそれらのスタックサイズの合計したものがスタック除去量になります。
  249.  
  250.  
  251. 【サンプルコード3】
  252.  
  253. このサンプルでは、MMX 命令や 3DNow! 命令のサンプルコードを書いておきます。ただし、動作内容については全くの無意味です。このようなニモニックが使用できることだけを参考にしてください。
  254.  
  255.                 .586
  256.                 .PentiumPro
  257.                 .MMX
  258.                 .3DNow
  259.                 .model  small, c
  260.  
  261. _text           segment para use32
  262.  
  263. MMX3DNow        proc    near
  264.                 arg     Para1:dword, Para2:dword
  265.                 
  266.                 femms
  267.                 prefetch        byte ptr ds:[edi*4+1000h]
  268.                 
  269.                 
  270.                 pfmul   mm1,mm2
  271.                 pfmul   mm1,[ebx]
  272.                 pfmul   mm1,[ebx+10]
  273.                 pfmul   mm1,es:[ebx]
  274.                 pfmul   mm1,[ebx+eax*4+10]
  275.                 
  276.                 fcomp   st(1)
  277.                 fcomi   st(0),st(1)
  278.                 
  279.                 cmova   eax,ebx
  280.                 cmove   ebx,ds:[edi]
  281.                 mov     eax,Para1
  282.                 add     eax,Para2
  283.                 
  284.                 paddw   mm0,mm1
  285.                 psubsw  mm0,mm1
  286.                 
  287.                 psllw   mm0,mm1
  288.                 psllw   mm1,5
  289.                 
  290.                 shl     eax,1
  291.                 
  292.                 movd    mm0,eax
  293.                 movd    mm0,ds:[eax]
  294.                 movd    mm0,dword ptr ds:[eax]
  295.         ;       movd     mm0,qword ptr ds:[eax]
  296.                 
  297.                 movq    mm0,qword ptr ds:[eax]
  298.         ;       movq    mm0,dword ptr ds:[eax]
  299.                 movq    mm0,mm1
  300.                 movq    mm0,ds:[eax]
  301.                 
  302.                 movq    ds:[eax],mm5
  303.                 movd    dword ptr ds:[eax],mm7
  304.                 movd    ecx,mm3
  305.                 
  306.                 emms
  307.                 
  308.                 ret
  309.                 
  310. MMX3DNow        endp
  311.  
  312. _text           ends
  313.                 
  314.                 end
  315.  
  316.  
  317.  
  318. 【nwsa を使う利点】
  319.  
  320.  Visual C++ では、C や C++ のソースファイル中に _asm 構文によってインラインアセンブラが使用できますが、単体のアセンブラが使用したくなるケースもあります。例えば、構造体をインラインアセンブラで使用することはできませんが、単体のアセンブラでは、struc, ends 構文にて使用できます。
  321.  
  322.  また、masm に比べると tasm と同様に構造体のメンバ指定が単純になっています。
  323.  
  324. 例えば、
  325.  
  326. SPerson         struc
  327.  
  328. SPName          db      16 dup (?)
  329. SPAge           db      ?
  330. SPSex           db      ?
  331. SPAddress       db      16 dup (?)
  332. SPTel           db      8 dup(?)
  333.  
  334. SPerson         ends
  335.  
  336.  
  337. PersonData      Sperson <>
  338.  
  339. に対し、
  340.  
  341.  
  342. 1.          mov      cl,PersonData.SPAge
  343.             
  344. 2.          mov      esi,offset PersonData
  345.             mov      cl,ds:[esi].SPAge
  346.  
  347. のいずれでも記述できます。MASM では後の方の記述は不可能で、
  348.  
  349. 3.          mov      esi,offset PersonData
  350.             mov      cl,ds:[esi].SPerson.SPAge
  351.  
  352. など、構造体のメンバを指定するのにその都度、構造体の型名を指定する必要があります。この仕様はメンバの名前空間を構造体内部にとどめることが出来ますが、アセンブラではアドレス指定にさまざまなケースが考えられ、この仕様では経験的に記述が面倒になります。
  353.  
  354.  
  355. 【現在の重大な制限事項】
  356.  
  357. 1. struc,ends による構造体型を定義時に、メンバのデフォルト初期化値が無視される。
  358. 2. 構造体型の変数の定義時、オペランドが完全に無視され、何を書いてもひとつ分の構造体が埋め込まれる。
  359. 3. extrn 宣言において構造体が使用できない。
  360. 4. db,dw,dd,df,dq  等において繰り返し回数の大きい dup 演算子を使うとアセンブル速度が極端に遅くなる。
  361. 5. end 文において start ラベルが指定できない。
  362.  
  363.  
  364. 【著作権について】
  365.  
  366.  MASM は単独では現在でも3万5000円程度で販売されています。
  367.  
  368.  MASM(ML.EXE) が Visual Studio 製品を持っているかどうかにかかわらず無料でダウンロードできるようになっているサイトもあるようですが、違法です。このようなサイトから偶然、ML.EXE というファイルをダウンロードしてしまった場合、速やかにハードディスク等から削除して使用しないようにして下さい。そのまま使用しつづけることも違法行為です。また、もしこのようなサイトを見つけた場合は、“コンピュータソフトウェア著作権協会“等に連絡してみてください。
  369.  ただし、MASM は、Visual Studio 製品を持っている場合は、Visual Studio Processor Pack という名称で無料で Microsoft サイトからダウンロードできます。
  370.  
  371.  一方、NWSA はアセンブラの文法が MASM に準拠しているのみで、プログラム自体は0から作成されたものです。したがって著作権は完全にNOWSMARTSOFTにあります。よって、NWSA は、NOWSMARTSOFTが自由に配布や販売する権利を有します。この点を誤解無きようお願いします。
  372.  
  373.  
  374. 【サポート事項】
  375.  
  376. ・整数命令のサポート:
  377.   次に列挙するものを除く 8086,80186,80286,80386,80486,Pentium,PentiumPro の全MPU命令をサポートしている。
  378.  ・LODS mem , STOS mem , MOVS mem,mem , CMPS mem,mem , SCAS mem
  379.    INS mem,dx , OUTS dx,mem
  380.   ・ただし、lodsb,lodsw,lodsd 等は使用できる。
  381.  ・現在のところ jmp far ptr , call far ptr でセグメントが埋めこまれない
  382.  
  383. ・486 で追加された全命令をサポートしている。
  384. ・Pentium で追加された全命令をサポートしている。
  385. ・PentiumPro で追加された全命令をサポートしている。
  386. ・MMX 命令を全命令サポートしている。cf.  .MMX 擬似命令, .NOMMX 擬似命令
  387. ・3DNow! 命令を全命令サポートしている。cf.  .3DNOW 擬似命令, .NO3DNOW 擬似命令
  388.  
  389. ・浮動小数点命令のサポート:8087,80287,80387 の命令および、PentiumPro で
  390.   追加された全浮動小数点命令をサポートしている。
  391.  
  392.  
  393. ;一行コメントを利用できる
  394. ";" コメント
  395. ;複数行にわたるコメントを記述できる
  396. COMMENT <Mark>・・・<Mark>
  397.  
  398. ;条件に応じてアセンブル動作を変更可能な構造化 IF 擬似命令が使用できる
  399. IF              <const>
  400. IFE             <const>
  401. IFDEF           <name>
  402. IFNDEF          <name>
  403. IFB             <<x>>
  404. IFNB            <<x>>
  405. IFIDN           <<x>>,<<y>>
  406. IFDIF           <<x>>,<<y>>
  407. IFIDNI          <<x>>,<<y>>
  408. IFDIFI          <<x>>,<<y>>
  409. IF1
  410. IF2
  411. ELSEIF          <const>
  412. ELSEIFE         <const>
  413. ELSEIFDEF       <name>
  414. ELSEIFNDEF      <name>
  415. ELSEIFB         <<x>>
  416. ELSEIFNB        <<x>>
  417. ELSEIFIDN       <<x>>,<<y>>
  418. ELSEIFDIF       <<x>>,<<y>>
  419. ELSEIFIDNI      <<x>>,<<y>>
  420. ELSEIFDIFI      <<x>>,<<y>>
  421. ELSEIF1
  422. ELSEIF2
  423. ENDIF
  424. ELSE
  425.  
  426. ・四則演算、論理演算、ビット演算の他、式中で多彩な演算子を使用できる。
  427. ・() によって優先順位を変更できる
  428. ・分岐命令において short と明示したものはエラーになるか、short ラベルしか生成
  429.  しない。
  430. ・分岐命令において near と明示したものはエラーになるか、near ラベルしか生成
  431.  しない。
  432. ・分岐命令において far と明示したものはエラーになるか、far ラベルしか生成
  433.   しない。
  434. ・分岐命令において距離を明示せず、かつ near ラベルを使用していれば、near
  435.   または short が自動生成される。
  436. ・分岐命令において距離を明示せず、かつ far ラベルを使用していれば、必ず far
  437.   命令が生成される。
  438.  
  439. ソースファイルの任意の位置でアセンブルを中断できる
  440. END
  441.  
  442. 任意のオフセットからコードを展開できる
  443. ORG <オフセット>
  444.  
  445. アラインメントを調整できる
  446. EVEN
  447. ALIGN <アラインメント>
  448.  
  449. セグメントレジスタに入っている値をアセンブラに知らせる事が出来る
  450. ASSUME <セグメントレジスタ>":"(<セグメント名>|<グループ名>)
  451.        {","<セグメントレジスタ>":"(<セグメント名>|<グループ名>)}
  452.  
  453. デフォルトの基数を変更できる
  454. .RADIX <基数>
  455.  
  456. 任意の複数行を引数付きでマクロ定義出来る
  457. ・引数付マクロを利用できる
  458. ・現在のところネスト不可
  459. ・LOCALを指定することでローカルラベルが使用可能
  460. ・EXITM を実行するとマクロ展開を中断できる
  461. <NAME>  MACRO~ENDM
  462.  
  463. 任意の複数行を繰り返す事が出来る
  464. ・ネストが可能
  465. ・= ラベルによって変化する値を扱える
  466. ・EXITM を実行すると繰り返しを中断できる
  467. REPT<回数>~ENDM        ;ネスト可能
  468.  
  469.  
  470. ネストして何度でもファイルを INCLUDE 出来る
  471. INCLUDE
  472.  
  473. 外部ラベルを参照できる
  474. EXTRN
  475. ラベルをPUBLIC宣言できる
  476. PUBLIC
  477.  
  478. DB
  479. DW
  480. DD
  481. DF
  482. DQ
  483. DT
  484.  
  485. NEAR ラベルを定義できる。PROC 中ではローカルラベルになる
  486. <NAME>:
  487. NEAR ラベルを定義できる。PROC 中でもグローバルラベルになる
  488. <NAME>  LABEL
  489.  
  490. 評価値記憶型非固定一行マクロ定義
  491. ・定義時に評価値として有効なもののみ定義できる
  492. ・何度でも定義できる
  493. ・使用される前に定義済みでなければならない
  494. <NAME>  =
  495. トークン記憶型固定一行マクロ定義
  496. ・定義時にはトークン自体を記憶するので、任意の項目が記憶できる。
  497. ・1トランスレーション単位では一意的な値しか記憶できない。
  498. ・フェーズエラーが発生する可能性は有るが、前方定義も可能。
  499. <NAME>  EQU
  500.  
  501. マルチセグメントモデルのプログラムを開発可能
  502. <NAME>  SEGMENT
  503. <NAME>  ENDS
  504.  
  505. 論理的に分かりやすいプロシージャ機能が使用可能
  506. ・ プロシージャ内部で定義したラベルは -pl オプションを指定しているとローカルな名前空間に記憶され、プロシージャ外部からは見えなく出来る。これによって良く似たサブルーチンを作成するときはラベル名の変更の必要が無く、単にコピーするだけでよい。
  507. ・ C言語の仕様と同様にPROC-ENDPをネストすると外側の名前空間で定義した名前を を内側から参照できる
  508. ・ 上記のようにPROC内部で定義したラベルは、-pl オプションを指定しているとローカルラベルになるが、LABEL 命令で定義したラベルは、常にグローバルな名前空間に登録され、全てのソース位置から参照できるようになる。
  509. ・ -pl オプションを指定しないと、プロシージャ内部のラベルもグローバルな名前空間に登録される。
  510. ・ ARG 擬似命令によって、cdecl 呼び出しの引数をサポートしている(TASM 互換)。
  511. ・ ARG 擬似命令を用いずに、PROC に続けて引数を指定することも出来る(MASM 互換)。
  512. ・ LOCAL 擬似命令によって、スタックローカル変数(AUTO 変数)をサポートしている。
  513. ・ ARG 擬似命令や LOCAL 擬似命令は、同一行にコンマで区切って複数の変数を指定できるだけでなく、複数行に繰り返し指定することが出来る。
  514. ・ ARG や LOCAL で指定された変数はプロシージャ内部の名前空間に登録される。
  515.  
  516. <NAME>  PROC      [<NEAR|NEAR16|NEAR32|FAR|FAR16|FAR32|PROC>]
  517.                   [PUBLIC|PRIVATE] [Arg01:type01, Arg02:type02, ...]
  518.         ARG     Arg11:type11, Arg12:type12, ...
  519.         ARG     Arg21:type21, Arg22:type22, ...
  520.         LOCAL   Work31:type31, Work32:type32, ...
  521.         LOCAL   Work41:type41, Work42:type42, ...
  522.  
  523. <NAME>ENDP
  524.  
  525. <NAME>STRUC
  526. <NAME>ENDS
  527.  
  528. .ERR
  529. .ERRNZ          <const>
  530. .ERRE           <const>
  531. .ERRDEF         <name>
  532. .ERRNDEF        <name>
  533. .ERRB           <<x>>
  534. .ERRNB          <<x>>
  535. .ERRIDN         <<x>>,<<y>>
  536. .ERRDIF         <<x>>,<<y>>
  537. .ERRIDNI        <<x>>,<<y>>
  538. .ERRDIFI        <<x>>,<<y>>
  539. .ERR1
  540. .ERR2
  541.  
  542. .8086
  543. .186
  544. .286
  545. .386                    //386 の命令を使用できるようになる
  546. .486                    //486 の命令を使用できるようになる
  547. .586
  548. .286P
  549. .386P
  550. .486P
  551. .586P
  552. .Pentium                //.586 と同様の意味だが、PRIVILEGE かどうかは変化しない
  553.                         //Pentium で追加された命令を使用できるようになる。
  554. .PentiumPro             //PentiumPro で追加された命令を使用できるようになる。
  555. .PentiumII
  556. .PentiumIII
  557. .PentiumIV
  558.  
  559. .MMX                    //MMX 命令を使用できるようにする
  560. .NOMMX
  561.  
  562. .3DNOW                  //3DNow! 命令を使用できるようにする
  563. .NO3DNOW
  564.  
  565. .PRIVILEGE              //486P の P と同じ意味
  566. .NOPRIVILEGE           //PRIVILEGE の作用を打ち消す
  567.  
  568. .MODEL  <メモリモデル>[,<言語名>]
  569.  
  570. <メモリモデル>=(SMALL|COMPACT|MEDIUM|LARGE|HUGE)
  571. <言語名>=<C,STDCALL,SYSCALL,BASIC,FORTRAN,PASCAL>
  572.  
  573. <メモリモデル>  @CODESIZE       @DATASIZE
  574. SMALL           0               0
  575. COMPACT         0               1
  576. MEDIUM          1               0
  577. LARGE           1               1
  578. HUGE            1               2
  579.  
  580. <言語名>        宣言形式
  581. UNKNOWN     %s
  582. C               _%s
  583. STDCALL       _%s
  584. SYSCALL
  585. BASIC
  586. FORTRAN
  587. PASCAL
  588.  
  589. @CODESIZE=0 :   PROC PTR        =NEAR PTR
  590.                 PROC PROC       =PROC NEAR
  591. @CODESIZE!=0 :  PROC PTR        =FAR  PTR
  592.                 PROC PROC       =PROC FAR
  593.  
  594. ;セグメントの強制配置リンカオプションを指定出来る
  595. DOSSEG
  596.  
  597. ;特殊定数
  598. @DATASIZE       =0,1,2
  599. @CODESIZE       =0,1
  600.  
  601. //言語指定にかかわらず外部シンボルの先頭に下線"_"を付加する。
  602. .UNDERSCORE     
  603.  
  604. //言語指定にかかわらず外部シンボルの先頭に下線"_"を付加しない。
  605. .NOUNDERSCORE
  606.  
  607.  
  608. ;・TITLE 文字列は EQU での置換が行われない
  609. ;・ただし ; 以降の文字は除去される。
  610. TITLE   <タイトル>
  611.  
  612. ;・%OUT 文字列はトークンとして解釈されてから表示される。
  613. ;・任意の空白はトークンの区切りとしてのみ意味を持ち、空白は保持されない。
  614. ;・少なくとも片方のトークンが記号以外であるトークンが接している場合は自動
  615. ; 的に1つのスペース文字がその間に挿入される。
  616. %OUT    <表示トークン列>
  617.  
  618. オーバーライド
  619.  
  620. <SREG>:                 --->SREGを用いる事を強制する
  621. <SEGMNAME>:             --->セグメントでオーバーライドする
  622. <GROUPNAME>:            --->グループでオーバーライドする
  623.  
  624. ラベルを含んだ評価値には
  625. FrameReg : オーバーライド用セグメントレジスタ識別番号
  626.       メモリオペランドがある場合にオーバーライドするべきフレームレジスタ
  627. FrameNo  : オーバーライド用NAME識別番号
  628.           NAME識別番号はセグメント名、グループ名、ラベル名等、異なった名前
  629.           をもつ任意の種類の項目を一括して同じ領域に記憶し、区別するために
  630.           共通につけられた番号で、番号が分かると項目の種類とその修飾情報が
  631.           取得できる。例えば、実際に定義したセグメント名の識別番号とグルー
  632.           プ名の識別番号は必ず異なった値になる。(項目の種類が違う場合に同
  633.           じ番号が付けられ混同すること)はない。
  634.  
  635. を記憶する場所がそれぞれ一つづつある。
  636.  
  637. <SREG>: でオーバーライドすると、FrameRegは設定されるが、FrameNoは以前の設定
  638. されない。
  639. <SEGNAME>:や<GROUPNAME>:でオーバーライドすると、FrameNoは設定されるが、FrameReg
  640. は設定されない。
  641.  
  642. FrameReg はメモリオペランドを使うときのみ指定し、混乱を招くため即値オペラン
  643. ドには指定すべきではない。本アセンブラでは即値オペランドに<SREG>:でオーバー
  644. ライドすると警告を表示する。
  645.         mov     eax,ds:Label1           ;Ok
  646.         mov     eax,_DATA:Label1        ;Ok
  647.         mov     eax,offset ds:Label1    ;Warning
  648.         mov     eax,offset _DATA:Label1 ;Ok
  649. FreameNo が明示されないで FrameReg だけが指定された場合は、ASSUME から直接にFrameNo を決定する。
  650.  
  651. FrameReg が明示されないで FrameNoだけが指定されたメモリオペランドでは、ASSUME指定の情報を逆にたどって、使用するフレームセグメントレジスタを決定する。FrameNoで示されたフレームがセグメントレジスタにASSUME割り付けされていない場合はエラーを報告する。
  652.  
  653. FReg   FNo     I/M SEG-PREFIX OBJ-FRAME  エラー
  654. R_N    S_B     I   無付加     SEARCH_BAD 無
  655. R_N    指定    I   無付加     FNo        無
  656. 指定   S_B     I   無付加     Ass[FReg]  警告
  657. 指定   指定    I   無付加     FNo        警告
  658. R_N    S_B     M   REG_NOUSE  SEARCH_BAD 無
  659. R_N    指定    M   IAss[FNo]  FNo        無またはエラー
  660. 指定   S_B     M   FReg       Ass[FReg]  無
  661. 指定   指定    M   FReg       FNo        無
  662.  
  663. ※Ass[r] はセグメントレジスタ r に仮定されているセグメント又はグループの識別
  664.  番号を返す。
  665. ※IAss[n] はセグメント又はグループの識別番号 n を仮定しているセグメントレジス
  666.  タの番号を返す。条件を満たすセグメントレジスタが無い場合はエラーになる。
  667. ※SEG-PREFIX=REG_NOUSE は前置バイトを付加しないことを示し、I(即値)の無付加と
  668.  同様の意味を持つ。
  669. ※OBJ-FRAME=SEARCH_BAD はラベルが存在する場所によってオーバーライドすること
  670.  を示す。
  671. ※R_N は REG_NOUSE の略で FrameRegが明示的には指定されていないことを意味する。
  672. ※S_B は SEARCH_BAD の略で FrameNoが明示的には指定されていないことを意味する。
  673. ※初期値は FReg=REG_NOUSE,FNo=SEARCH_BAD である。
  674. ※ASSUME x:nothing と指定すると、Ass[x]=SEARCH_BAD になる。
  675.  
  676. 例:
  677. DGROUP  group   _DATA
  678.         assume  ds:DGROUP , es:_ANOTHER
  679.  
  680.         mov     eax,es:(DGROUP:Data1)
  681.         ;・実際のコードは ES: バイトが付く
  682.         ;・OBJ ファイルには DGROUP でオーバーライドすることを知らせる
  683.         ;・標準的なリンカではグループ全体の先頭からの相対アドレスが
  684.         ; offsetオペランドに埋めこまれる。
  685.         mov     eax,Data1
  686.         ;・実際のコードはセグメント前置バイトは着かない。
  687.         ; ・暗黙に DS がベースアドレスになる
  688.         ;・OBJ ファイルには Data1 自体によってオーバーライドすることを知らせる
  689.         ;・実際に Data1 がDGROUPに属しているならば、標準的なリンカでは、
  690.         ;  DGORUP: を付加したのと同じく、グループ全体の先頭アドレスからの相対
  691.         ; アドレスが offset オペランドに埋めこまれる。
  692.         mov     eax,es:Data1
  693.         ;・実際のコードは ES: バイトが付く
  694.         ;・OBJ ファイルには _ANOTHER によってオーバーライドすることを知らせる
  695.         ;・標準的なリンカではグループ全体の先頭からの相対アドレスが
  696.         ; offsetオペランドに埋めこまれる。
  697.         
  698.         mov     eax,offset _DATA:Data1
  699.         ;・OBJ ファイルには _DATA セグメントでオーバーライドすることを知らせる
  700.         ;・標準的なリンカではグループの途中のセグメントの先頭からの相対アド
  701.         ; レスが即値オペランドに埋めこまれる。
  702.         mov     eax,offset DGROUP:Data1
  703.         ;・OBJ ファイルには DGROUP でオーバーライドすることを知らせる
  704.         ;・標準的なリンカではグループの先頭からの相対アドレスが即値オペラ
  705.         ; ンドに埋めこまれる。
  706.         mov     eax,offset Data1
  707.         ;・OBJ ファイルには Data1 自体によってオーバーライドすることを知らせる
  708.         ;・標準的なリンカでは DGROUP の先頭からの相対アドレスが即値オペラ
  709.         ; ンドに埋めこまれる。
  710.  
  711.  
  712. 【非サポートまたは制限事項】
  713.  
  714. ・構造体の初期化が出来ない
  715. ・構造体のデフォルト値の意味が無い
  716. ・extrn の型として構造体型を指定できない
  717. ・END 文に先頭番地を指定しても現在、正しく OBJ に書かれない
  718. ・REPT はネストできるが、MACRO はネスト出来ない
  719.  ・両者の混在は現在のところサポートしていない(動作不定)
  720. ・IRP,IRPC をサポートしていない
  721. ・マクロ展開時、EQU で置換後に EXITM が出現した場合、EXITM は働かない。
  722. ・PURGE をサポートしていない
  723. ・DB,DW,DD,DF,DQ,DT のサポートが甘い
  724.  ・現在、dd や df で far ptr を埋めこめない。
  725. ・浮動小数点定数が使えない
  726. ・簡易化セグメント擬似命令が使えない
  727. ・COMM をサポートしていない
  728. ・PUBLIC や EXTRN で AS による名前の付け替えが出来ない
  729. ・絶対値を PUBLIC 宣言できない
  730. ・絶対値を EXTRN で扱えない
  731. ・RECORD 文をサポートしていない
  732. ・LOCK 命令でLOCK出来る命令を厳密にはチェックしていない。
  733.  ・本来はLOCK化される命令がメモリオペランドを取っていることを調べる必要が
  734.   有る。
  735. ・PAGE,OPTION,NAME,SUBTITLE をサポートしていない
  736. ・.XLIST,.LIST,.LFCOND,.SFCOND,.TFCOND,.LALL,.SALL,.XALL,.CREF,.XCREF
  737.   をサポートしていない
  738. ・デバッグ情報は、COFF 形式の OBJ ファイルにのみ挿入できる。OMF 形式の OBJ
  739.   ファイルには挿入できない。
  740. ・ シンボルは無制限に登録可能だが、proc, endp で定義する関数の最大値は 65535 個に制限されている。
  741. ・ imm8 オペランドを自動生成しない。
  742. ・速度的な「詰めの作業」が全く行われていない。
  743. ・今のところ最低でも2パス必要なので速度的に多少問題が有る
  744.   ---> 以下のような技術を用いて1パスで終えるようにすべきである
  745.      ・jmp 命令オペランドのバックパッチによる埋め込み
  746.      ・jmp 命令のサイズのバックパッチ的な修正
  747.  
  748. 【将来】
  749.  
  750.  このプログラムのソースを希望があれば、有料(10万円程度)で公開しようと思っています。
  751.  
  752.  
  753. 【連絡先】
  754.  
  755.  本アセンブラに関してのご質問は、次の E-MAIL アドレスにお願いします。前向きなご意見やご要望も承っておりますので是非お気軽にメイルください。
  756.  また、専用のホームページにて会議室(BBS)を開いております。お気軽にご意見をお書き込み下さい。
  757.  
  758. E-Mail:                 LightCone@nifty.ne.jp (KHF12570@nifty.ne.jp と同一)
  759.  
  760. ホームページURL:        http://homepage2.nifty.com/nowsmart/
  761.  
  762.  
  763. 【Update 情報】
  764.  
  765. 2001/02/23  NWSA140.LZH
  766.  
  767. 修正項目        PROC の引数を、ARG 擬似命令を用いず直接指定できるようにもし、MASM の書式に対応した。
  768. 原因            関数の引数は、PROC の次の行から、ARG 擬似命令を用いて指定する方法(TASM仕様)のみに対応していた。
  769. 対処            PROC 擬似命令の NEARや PUBLIC 指定に引き続き、引数を指定できるようにした。
  770.  
  771.  
  772.  
  773. 2001/02/23  NWSA130.LZH
  774.  
  775. 修正項目        PROC~ENDP内部で LOCAL変数(AUTO 変数)が使用できるようになった。
  776. 原因            LOCAL 擬似命令をサポートしていなかった。
  777. 対処            LOCAL 擬似命令をサポートした。
  778.  
  779. 修正項目        PROC~ENDP 内部で ARG や LOCAL を指定しなかった場合はスタックフレームを生成しないようにした。
  780.                 スタックフレームとは、
  781.                 push    ebp
  782.                 mov     ebp,esp
  783.                 sub     esp,8
  784.                 ~
  785.                 mov     esp,ebp
  786.                 pop     ebp
  787.                 のようなコード。
  788. 原因            PROC~ENDP では無条件にスタックフレームを作成していた。
  789. 対処            ARG や LOCAL が使用されているかどうかによってスタックフレームを作成するかどうかを自動判別
  790.                 するようにした。
  791.  
  792.  
  793. 修正項目        PUBLIC や EXTRNで外部に公開されるシンボルの先頭に下線を付加するかどうかを、個別に指定でき
  794.                 るようにした。
  795. 原因            .MODEL 命令で言語をCやSTDCALL に指定したときは必ず下線を付加していた。
  796. 対処            .UNDERSCORE 擬似命令と.NOUNDERSCORE 擬似命令を追加し、強制指示できるようにした。
  797.  
  798.  
  799. 2001/01/21  NWSA120.LZH
  800.  
  801. 修正項目        シンボルの最大定義数を固定ではなく、無制限にした。
  802. 原因            シンボルの格納方法が固定型だった。
  803. 対処            シンボルの格納方法を可変型にした。
  804.  
  805.  
  806.  
  807.  
  808. 2001/02/04  NWSA111.LZH
  809.  
  810. 修正項目        mov eax,dword ptr -1 等としたときに、-1 が文法エラーになってしまうバグを修正。
  811. 原因            ???? ptr の後につく文法要素を文法定義段階でミスしていた。
  812. 対処            文法要素を正しく修正。
  813.  
  814. 修正項目        フェーズエラーが何パスにも渡り延々と生じるバグを修正。
  815. 原因            ラベルフェーズエラーが生じたとき、それ以後のラベルフェーズエラーを事前に予測し、
  816.                 ラベルの値を自動修正するプログラムにおいて、負の値の加算値に対して動作がおかし
  817.                 くなっていた。
  818. 対処            変数を符号付きから符号無しへ修正。
  819.  
  820. 修正項目        セグメントオーバーライドを明示しなかった場合に、ASSUME 指定の内容から自動的
  821.                 にセグメントレジスタを選び出すアルゴリズムにおいて、選び出す優先順位が適切で
  822.                 なかたった部分を修正。
  823. 原因            セグメントレジスタの選択アルゴリズムにおいて、レジスタの命令イメージの順に探していた。
  824. 対処            スタック以外では、
  825.                 DS,CS,SS,ES,FS,GS
  826.                 スタックでは、
  827.                 SS,DS,CS,ES,FS,GS
  828.                 
  829.                 の順に優先順位を付けて探すようにした。
  830.  
  831.  
  832. 2001/01/30  NWSA110_2.LZH
  833. ドキュメントをTXT形式からワード形式に変更して整理。追加。
  834.  
  835.  
  836. 2001/01/28  NWSA110.LZH
  837. NOWSMART ASSEMBLER VER 1.10 としてあらためて公開。
  838.              ファイルネームを SASM.EXE から NWSA.EXE に変更。
  839.              COFF 形式に対応。
  840.              COFF 形式においては、行番号デバッグ情報を埋め込めるように
  841.              した。
  842.              同じセグメントの offset アドレスを書き込むときのリロケーション
  843.              情報の誤りを是正。
  844.              SAMPLE.ASM を書いておいた。
  845.              STARTUP.TXT を書いておいた。
  846.  
  847.  
  848. 2001/01/23   SASM100.LZH
  849. SMART ASSEMBLER VER 1.00  としてまだ非公開のホームページに
  850.              載せてみた。
  851.              ファイルネームは SASM.EXE
  852.              COFF 形式には全く未対応。
  853.  
  854.  
  855.