トップ

プログラム開発環境 version 1.27

最新版のダウンロード

http://www001.upp.so-net.ne.jp/isaku/build.zip

●ファイル一覧

build.htmlこのファイル。
MakeBcc.batn.exe , build1.exe , build2.exe を作成します。
n.c , n.ico 行番号を付けることが可能なエディター。build1 と build2 で呼び出されます。
build1.c C , C++ , MASM32 をコンパイルします。余計な中間ファイルを自動削除します。
build2.c , build2.h C を MASM32 経由でコンパイルします。exe ファイルが非常に小さくなるのが長所です。

●MakeBcc.bat による exe ファイルの作成

まず、「Borland C++ Compiler 5.5.1」と「masm32」をインストールしてください。 「Borland C++ Compiler 5.5.1」は、

http://www.codegear.com/jp/downloads/free/cppbuilder

からダウンロードできます。必ずデフォルトの位置にインストールしてください。

上手くいかない人は以下のページからダウンロードしてインストールしてください。

http://www.vector.co.jp/soft/win95/prog/se326602.html

http://www.geocities.jp/katayama_hirofumi_mz/bccinst/

「masm32」は、http://www.masm32.com/の でダウンロードできます。

「masm32」は、必ずCドライブにインストールしてください。 そしたら、MakeBcc.bat を実行してください。 n.exe , build1.exe , build2.exe が完成します。 これらのファイルのショートカットを SendToフォルダに置くか、 Windows の[フォルダオプション]の[ファイルの種類]を設定して使いやすくしてください。

●n.exe

N.exe は Notepad.exe を呼び出します。必要に応じて Wordpad.exe を呼び出します。
最初に -g があれば行番号を付けたものを一時ファイルとして作成しメモ帳で開きます。 もし、一時ファイルが変更されれば、行番号を取り除いて、元のファイルに書き戻します。
-b は、-g と同じですが、画面の右下にウィンドウを移動します。
最初に -n があれば、行番号は付けません。
N -68 a.c のように指定すると a.c を68カラムで開きます。
N -68 -25 a.c のように指定すると、68×25で開きます。
-g で、行番号を付けて開いた場合、タブ文字は4文字のスペースに変換されます。
[F3]キーを押すことにより、目的の行番号へジャンプできるので、便利です。

●build1.exe

build1.exe。基本と共通事項

●build1.exe は、拡張子に応じてコンパイルします。

例 > build1 test.c
   > build1 test.cpp
   > build1 test.asm
いずれの場合も、test.exe が作成されます。不要になった、 オブジェクトファイルなどは自動的に削除されます。

●-r オプションにより自動実行ができます。

例 > build1 -r test.c
-r オプションを付けると、作成された test.exe を実行し、 プログラムが終了したら exe ファイルも削除します。
exe ファイルにパラメータを付けて実行することもできます。
例 > build1 -rfile.txt test.c
   > build1 -r"-A file.txt" test.c
上の例の場合「test.exe file.txt」が実行されます。
下の例の場合「test.exe -A file.txt」が実行されます。

●複数のソースファイル分かれたプログラムもコンパイルできます。

例 > build1 test.c sub1.c sub2.c
この場合、3つのファイルをコンパイルしてリンクし、test.exe が作成されます。

●-n オプションにより、exe ファイルがソースファイルよりも新しい場合はスキップできます。

例 > build1 -n test.c sub1.c sub2.c resource.h
-n オプションは、スキップすると同時に、確認のキー入力を待ちません。 複数ファイルの場合は、.bat ファイルに書いておくと便利です。

build1.exe。CとC++の場合

●ウィンドウズアプリケーションかコンソールアプリケーションかどうかを自動判別して コンパイルします。
指定したソースファイルの中に "WinMain" があれば、 ウィンドウズアプリケーションとしてコンパイルされます。 また、"DllMain" があれば、DLL ファイルがコンパイルされます。 そうでなければ、コンソールアプリケーションとして、コンパイルされます。

●ソースファイルが全てCの場合、NOEH32.LIB がリンクされます。 C++ファイルが一つでも指定されると NOEH32.LIB がリンクされないので、 出来上がる exe ファイルがCのみの場合に比べて大きくなります。

●ファイル名の拡張子を除いた部分が同じで、拡張子が .rc のリソースファイルがある場合は、 このリソースファイルもコンパイルされてリンクされます。

例 > build1 test.c
の場合、test.rc が同じフォルダに存在すれば、リンクされます。

●リソースファイルが無く、.ico ファイルが存在すれば、 .ico ファイルが自動的にリンクされます。

例 > build1 test.c
の場合、同じフォルダにtest.rc が無く、test.ico が存在すれば、test.ico がリンクされます。 アイコンのリソースIDはIDI_APPLICATION(32512) です。

build1.exe。MASM32 の場合

●ウィンドウズアプリケーションかコンソールアプリケーションかどうかを 自動判別してリンクします。
指定したソースファイルの中に "CONSOLE" があれば、 コンソールアプリケーションとしてリンクします。 この時、大文字・小文字の区別はしません。 また、日本語で "コンソール"という文字列があった場合も、 コンソールアプリケーションとしてリンクされます。"CONSOLE" も "コンソール" もない場合は、 ウインドウズアプリケーションとしてリンクされます。

●rsrc.rc というリソースファイルが同じフォルダに存在すれば、 コンパイルされてリンクされます。

例 > build1 test.asm
の場合、rsrc.rc が同じフォルダに存在すればリンクされます。

●リソースファイルが無く、.ico ファイルが存在すれば、 .ico ファイルが自動的にリンクされます。

例 > build1 test.asm
の場合、同じフォルダに rsrc.rc が無く、test.ico が存在すれば、test.ico がリンクされます。 アイコンのリソースIDはIDI_APPLICATION(32512) です。

build1.exe。オプション一覧

 -b : bcc32 に渡すパラメータ。
 -c : Console アプリケーションに強制。
 -D : マクロの定義。
 -l : link に渡すパラメータ。
 -m : ml に渡すパラメータ。
 -n : 日付をみて不要ならコンパイルしない。同時に、キー入力を待たない。
 -r : できたファイルを実行したあと消す。続けてパラメータも指定できる。
 -w : Windows アプリケーションに強制。

●build2.exe

build2.exe。特徴

例えば、hello.c を、
#include <stdio.h>
int main(void)
{
    printf("Hello\n");
    return 0;
}
として、> bcc32 hello.c でコンパイルすると、作成される hello.exe の大きさは 52,224 バイトになります。> build1 hello.c でコンパイルすると NOEH32.LIB がリンクされて小さくなりますが、それでも 35,840 バイトです。
これを > build2 hello.c でコンパイルすると、作成される .exe ファイルの大きさは、 たったの 5,632 バイトです。また、printf( ) が浮動小数点数を使っていないので、 -u オプションが使用できます。> build2 -u hello.c でコンパイルすると、 ファイルの大きさはさらに縮まり、1,536 バイトになります。
char __uprintf;
のように、プログラムにダミーのグローバル変数を宣言すれば、-u オプションを 指定したのと同じになります。 build2 や -u オプションには色々制限がありますが、工夫次第で回避できるので、 どうぞ挑戦してみてください。※printf( ) の代わりに puts( ) を使えば、 さらに長い文字列を出力しても 1,024 バイトで済みます。

finit

char __nofinit;
のように、プログラムにダミーのグローバル変数を宣言すれば、finit を実行しません。

build2.exe。使い方

build2.exe は build1.exe と違い、1つのC言語ファイルしか、指定できません。 また、C++には対応していません。
WinMain があるときは、ウィンドウズアプリケーションとしてコンパイルされます。
DllMain があるときは、dll ファイルが作成されます。
それ以外の場合はコンソールアプリケーションとしてコンパイルされます。
ファイル名の拡張子を除いた部分が同じで、拡張子が .rc のリソースファイルがある場合は、 このリソースファイルもコンパイルされてリンクされます。 このリソースファイルがなく、かつ、拡張子が .ico のファイルがある場合は、 この .ico ファイルがリンクされます。
Cファイルをコンパイルされる時、#define シンボル MASM32 が定義されます。
デフォルトのインクルードファイルとライブラリは windows.inc に加えて、 user32 , kernel32 , gdi32 , winspool , shell32 , advapi32 , comctl32 , comdlg32 , ole32 , oleaut32 , uuid , odbc32 , winmm , version , wininet , imm32, psapi の、各 .inc ファイルと .lib ファイルです。これらで、ほとんどの主要な Win32 API 関数を使うことができます。もし、他の API 関数を使いたい時、 例えば randlib.inc, dsound.inc, randlib.lib, dsound.lib を追加したい時は、 オプション -irandlib,dsound のようにカンマで区切って指定します。

build2.exe。対応非API関数・変数・マクロ一覧

 abort     abs       acos      _argc     _argv     asin       assert     atan
 atan2     atexit    atof      atoi      _atoi64   atol       bsearch    calloc
 ceil      cgets     chdir     clock     cos       cosh       cprintf    cputs
 cscanf    difftime  div       ecvt      environ   _environ   errno      exit
 _exit     exp       fabs      fclose    fcvt      feof       fflush     fgetc
 fgetchar  fgets     floor     fmod      fopen     fputc      fputchar   fputs
 fprintf   fputc     fread     free      frexp     fscanf     fwrite     gcvt
 getc      getch     getchar   getche    getcwd    getenv     gets       hypot
 _i64toa   isalnum   isalpha   isascii   iscntrl   __iscsym   __iscsymf  isdigit
 isgraph   islower   isprint   ispunct   isspace   isupper    isxdigit   itoa
 kbhit     labs      ldexp     lfind     log       log10      lsearch    ltoa
 malloc    memccpy   memchr    memcmp    memcpy    memicmp    memmove    memset
 mkdir     modf      perror    printf    pow       putc       putch      putchar
 putenv    puts      qsort     rand      realloc   remove     rename     rmdir
 scanf     sin       sinh      sprintf   sqrt      srand      sscanf     strcat
 strchr    strcmp    strcpy    strcspn   strdup    stricmp    strlwr     strncat
 strncmp   strnicmp  strnset   strlen    strncpy   strpbrk    strrchr    strrev
 strspn    strset    strstr    strtod    strtok    strtol     strtoul    strupr
 system    tan       tanh      time      toascii   tolower    _tolower   toupper
 _toupper  _ui64toa  ultoa     ungetc    ungetch   unlink
拡張機能として、getch , getche , kbhit , cgets , cscanf はマウスが左クリックされると [ENTER]キーを押したとみなされます。
標準C言語ライブラリをできるだけ使わず、Win32 API を使うことを推奨します。

build2.exe。制限事項

●グローバル変数やスタティック変数が1メガバイトを超えると、 アセンブルする時間が長くなります。 アセンブル時間を短くするためには、 巨大なグローバル変数やスタティック変数をcalloc()やmalloc()で 確保するようにプログラムを書き換えなければなりません。

●fopen( ) で読み書きオープンができません。 ファイルのアクセス指定子に "r","rb","w","wb","a","ab" しか指定できません。 これら以外を指定すると NULL を返します。

●time( ) は、ウィンドウズを起動してからの秒数を返します。 従って、使用目的が、プログラムの経過時間の計測や、乱数の種の設定などに限られます。

●errno を設定するのは atof( ), strtod( ), strtol( ), strtoul( ) のみです。

●perror( ) は、GetLastError() のみ参照します。errno は無視します。 従って、atof( ) 等で errno が ERANGE にセットされても、反映されません。

●数学関数はエラーチェックをしていません。

●DLL ファイルをコンパイルする場合、グローバル変数を使っている非API関数は、 問題を起こす可能性があります。できるだけWin32API関数を使ってください。

●DLL ファイルをコンパイルする場合、eax などのレジスタ名、test や mov など命令名を エキスポートすることはできません。

●-u オプションでの printf( ),fprintf( ),sprintf( ),cprintf( ) の問題点。
これらは内部で wvsprintf( ) を使っているので、ファイルサイズを大幅に減らせますが、 以下の制限があります。
・浮動小数点を書き出せません。 対策として、%s と gcvt( ) を組み合わせて使うとよいでしょう。
・__int64 を書き出せません。通常の printf( ) では "%I64d" のように指定すると、 __int64 値を書き出せますが -u オプションでは書き出せません。 対策として、%s と _i64toa( ) を組み合わせて使うとよいでしょう。
・8進数で書き出せません。 対策として、%s と itoa( ) を組み合わせて使うとよいでしょう。
・書き出せる最大の文字数が 1024 バイトに制限されています。 対策として、一つの printf( ) 文を、複数の printf( ) 文に分けるか、fputs( ) を使います。
・文字幅指定子'*'を使うことができません。
・sprintf( ) のバッファは、書式制御文字列よりも大きくないとエラーになる可能性があります。

build2.exe。-t オプション

-t オプションを指定すると文字列リテラルが書き込み可能になります。 下のプログラムを使って説明します。
#include <stdio.h>
int main(void)
{
    char*a="C:\\My Documents";
    a[0]='D';
    printf("%s\n",a);
    return 0;
}
このプログラムを VC++ や -t オプションを使用ない build2 で実行するとエラーになります。 しかし、bcc32、build1、-t オプションを使用した build2 で実行すると、
D:\My Documents
が出力されます。ちなみに、変数 a の宣言を
char a[ ]="C:\\My Documents";
とすると、どのコンパイラでもエラーを防ぐことができます。

build2.exe。挿入ソート

qsort( ) と同じ使い方をする挿入ソート、isort( ) を用意しました。 プロトタイプも、qsort( ) と同じです。 アルゴリズムは以下のとおりです。とてもシンプルです。
double a[N];
void InsSort(void)
{
    int i,j; double x;

    for (i=1;i<N;i++) if (a[i-1]>a[i]) {
         x=a[i]; j=i-1;
         do { a[j+1]=a[j]; j--; } while (j>=0&&a[j]>x);
         a[j+1]=x;
    }
}
特徴は、小さなデータを何回もソートたり、既に整列されていたり、 あるいは、ほぼ整列されているデータをソートする場合に qsort( ) よりも高速になることです。 次は、配列を乱数で成長させながら、その都度ソートして、isort( ) が qsort( ) より 約4〜7倍高速になる例です。build2 以外でコンパイルできるように、 isort のソースをつけました。これは、x をヒープにとり、memcpy を呼び出していますが、 build2 で出力される isort( ) では x はスタックにとられ、memcpy の代わりに rep movsd と rep movsb が埋め込まれ、高速化されます。また、build2 で出力される qsort( ) は、bcc32 の qsort( ) よりも高速化されています。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
void isort(void*,size_t,size_t,int(*)(const void*,const void*));

#ifndef MASM32
void isort(void*base,size_t n,size_t w,
           int(*cmp)(const void*,const void*))
{
    char*i,*j,*x;

    n=(int)base+n*w; x=malloc(w);
    for (i=(char*)base+w;i<(char*)n;i+=w)
     if (cmp(i-w,i)>0) {
         memcpy(x,i,w); j=i-w;
         do { memcpy(j+w,j,w); j-=w; }
         while (j>=(char*)base&&cmp(j,x)>0);
         memcpy(j+w,x,w);
     }
    free(x);
}
#endif

#define N 10000 /* 成長とソートする回数 */
int a[N][4],i,lap; /* 変数 */

/* 比較関数 */
int comp(const void*a,const void*b) { return*(int*)a-*(int*)b; }

/* 実験マクロ */
#define TEST(SORT) \
 srand(1); lap=clock(); \
 for (i=0;i<N;i++) { a[i][0]=rand(); SORT(a,i+1,sizeof*a,comp); } \
 printf("%s : %d msec\n",#SORT,clock()-lap)

int main(void) { TEST(isort); TEST(qsort); return 0; }

build2.exe。オプション一覧

 -a : アセンブラのソースを生成するだけ。
 -b : bcc32 に渡すパラメータ。
 -c : Console アプリケーションに強制。
 -D : マクロの定義。
 -i : インクルードファイルとライブラリを追加。
 -l : link に渡すパラメータ。
 -m : ml に渡すパラメータ。
 -n : キー入力を待たない。
 -r : できたファイルを実行したあと消す。続けてパラメータも指定できる
 -t : 文字列リテラルを書き込み可能にする。
 -u : printf() 系で浮動小数点数を使わない。
 -w : Windows アプリケーションに強制。
 -x : rand(),srand() を XorShift にする。