2007年3月 4日
Light Macro Assembler
最近、ハンド・アセンブルのブログを何本か書いてきたが 種を明かすと、 はじめは、実際にハンド・アセンブルしていたのだが、 少し複雑になってくると、ハンド・アセンブルするのが面倒くさくなり 部分的にアセンブラを使うことにした。以前は、マイクロソフト(Microsoft)のMASMも使っていたので、 家のどこかを探せば見つかるとは思ったのだが、 それを見つけ出す気力もなくて、 何か簡単にアセンブルする方法はないかと探してみた。
そこで見つけたのが、 「Light Macro Assembler」 である。 マイクロソフト(Microsoft)のMASMと互換性のある アセンブラ・ソフトらしい。 売り物のソフトではあるが、 親切にも体験版がダウンロードでき、 100 行未満のプログラムであれば、問題なく動作するようだ。
早速ダウンロードして、 サンプルの「helloc.asm」を参考にしながら 今までハンド・アセンブルしていたソースを書いてみた。 その結果が
.model tiny ; COM 形式には TINY モデルを指定 .code ; セグメントの開始 org 100h mov dl, 53h ; 「S」の字の ASCII文字コード を DLレジスタにセット mov ah, 02h ; 出力に1文字出力するファンクションコールを指定 int 21h ; MS-DOSファンクションコール xor dl, 20h ; 大文字/小文字を変換 int 21h ; MS-DOSファンクションコール int 20h ; プログラムの終了 endとなった。 このソースを「disp3.asm」として保存後、 アセンブル および リンク してみる。 この時の注意点は、.com モデルをリンク際には、「/C」オプションが必要なこと。
C:\LASM>lasm disp3 Light Macro Assembler for x86 Version 2.35C 【体験版】 Copyright (C) Tama Software Ltd., 1991-2003. (http://www.tamasoft.co.jp/) disp3.asm ?_DUMMY ........ 0 bytes (DGROUP) _TEXT .......... 269 bytes (DGROUP) Total .......... 269 bytes C:\LASM>lil disp3 /c Light Linker Version 2.40F Copyright (C) Tama Software Ltd., 1991-2003.【体験版】 実行ファイル disp3.com を作成しました. C:\LASM>とすると、disp3.com が出来上がっている。 出来あがった disp3.com の内容を Windows用バイナリエディタ 「Stirling(スターリング)」 で確認してみると、 「B2, 53, B4, 02, CD, 21, 80, F2, 20, CD, 21, CD, 20」 となっており、ハンド・アセンブルした内容と一致していることが 確認できる。
ウィンドウズ・ユーザーでアセンブラを試してみたいなら お手軽なので、Light Macro Assembler の体験版はお薦めである。
【参考リンク】
カテゴリー: プログラミング 22:01 | コメント (0) | トラックバック (0)
2007年3月 3日
わざと暴走させる1バイトのマシン語プログラム
前々回のブログまでの マシン語プログラム実験の続編として、 実際にプログラムを暴走させたらどうなるかを試してみよう。暴走させる最も簡単な方法は、CPUにHOLTをかけること。 そうすると、基本的にCPUの動作を停止してしまうので プログラムとしては反応しなくなり、リセット以外の道は なくなるはずである。
では、実際に実験してみる。 80x86系CPUにおける「HLT」命令の 16進コードは「F4」である。 前回のように Windows用バイナリエディタ 「Stirling(スターリング)」 を起動して、そこに「F4」と入力する。 これを適当なディレクトリに「HLT.com」というファイル名でセーブする。 このファイルをDOS窓のプロンプトからタイプして実行してみる。 案の定、DOS窓は何も反応しなくなった。
この実験は Windows 2000 上で行ったのだが、 当たり前のことではあるが最近のOSはさすがで、 当の DOS窓 はハングしてしまったが、ウィンドウズ自身は 全く問題なく動作していた。 これを実際のMS-DOSの上で実行したら、PC自身をリセットするしかない。 自分が PC-9801上で8086アセンブラのソフト開発していた頃には、 果たして何度 リセットボタンを押したことか、と昔を思い出してしまった。
カテゴリー: プログラミング 22:16 | コメント (0) | トラックバック (0)
2007年3月 1日
8086マシン語、ハンド・アセンブル実験(4)
最近、せっかく アセンブラをやってきているので、 もう少しだけ、変更してみる。前回のブログの最後に示した アセンブラのソースでは 単に「mov」命令を使っているだけで、 それでは能がないので、 4行目の「mov dl, 73h」を「or dl, 20h」と変更してみる。
「ASCII文字コード」を見てみると判るが、 アルファベットの大文字と小文字は、コードで 20h の差があることがわかる。 大文字を小文字に変換するためには コードで 20h を足す、 つまり、00100000B を or してやればよいことになる。 これで、1行目に設定した文字を小文字に変更することがきる。 すると アセンブラのソースは
mov dl, 53h ; 「S」の字の ASCII文字コード を DLレジスタにセット mov ah, 02h ; 出力に1文字出力するファンクションコールを指定 int 21h ; MS-DOSファンクションコール or dl, 20h ; dlの文字を小文字に変換 int 21h ; MS-DOSファンクションコール int 20h ; プログラムの終了となる。
「or dl, 20h」はコードにすると「80, CA, 20」となるので、 コード全体としては、 「B2, 53, B4, 02, CD, 21, 80, CA, 20, CD, 21, CD, 20」 となる。 これを実行してみるとうまくゆくが、 結局、実行結果は前回と全く変わらないことになる。
試しに、2バイト目の値を「J」を表す「4A」に変更してから 実行してみると、結果は
Jjとなる。
ただし、この方法だと、最初に設定した文字が小文字なら、 そのまま小文字が2回続けて表示されることになる。 それではつまらないので、もし小文字を設定した場合には 小文字と大文字が表示されるようにしてみる。 これは、4行目の「or dl, 20h」を 「xor dl, 20h」に変更するとよい。 コードとしては、「80, F2, 20」となるので、 コード全体としては、 「B2, 53, B4, 02, CD, 21, 80, F2, 20, CD, 21, CD, 20」 となる。 これを実行すると、 大文字の場合はその小文字が、小文字の場合は大文字が続けて表示されるようになる。
ここ何回かのブログでウィンドウズ・ユーザーが マシン語を体験できる方法を紹介してみたが、 これ以上複雑なことを マシン語でプログラムしようと思ったら ハンド・アセンブルではなく、素直にアセンブラ・ソフトウェアに 任せた方がよいであろう。
【参考リンク】
カテゴリー: プログラミング 22:47 | コメント (0) | トラックバック (0)
2007年2月28日
8086マシン語、ハンド・アセンブル実験(3)
前回のブログで マシン語プログラムを 実行するところまできたので、 今回はこのプログラムを少し改造してみよう。まず、前回のブログで実行したプログラムのソースは
mov dl, 53h ; 「S」の字の ASCII文字コード を DLレジスタにセット mov ah, 02h ; 出力に1文字出力するファンクションコールを指定 int 21h ; MS-DOSファンクションコール int 20h ; プログラムの終了で、これをハンド・アセンブルして16進数のコードしたのが 「B2, 53, B4, 02, CD, 21, CD, 20」 であった。
このコードの2バイト目の「53」が表示される文字のコードなので ここを他のコードに変更すると表示される文字を変えられる。 「ASCII文字コード」から 適当な文字のコードを探してみるとよい。 例えば、「53」から「73」に変更して 「B2, 73, B4, 02, CD, 21, CD, 20」 としてから、実行してみると 表示される文字が小文字の「s」になる。
では、もう少し改良を加えて、文字を2文字表示するようにしてみる。
mov dl, 53h ; 「S」の字の ASCII文字コード を DLレジスタにセット mov ah, 02h ; 出力に1文字出力するファンクションコールを指定 int 21h ; MS-DOSファンクションコール mov dl, 73h ; 「s」の字の ASCII文字コード を DLレジスタにセット int 21h ; MS-DOSファンクションコール int 20h ; プログラムの終了上の例では1文字目が「S」、2文字目が小文字の「s」を表示している。 これをコードにしてみると、 「B2, 53, B4, 02, CD, 21, B2, 73, CD, 21, CD, 20」 となる。これを例のごとく バイナリ・エディターで入力してから「disp2.com」という名前を付けて 保存後、実行してみると、
C:\TEST>disp2 Ss C:\TEST>となる。
【参考リンク】
カテゴリー: プログラミング 22:14 | コメント (0) | トラックバック (0)
2007年2月27日
8086マシン語、ハンド・アセンブル実験(2)
前々回のブログで、 実験用のアセンブラを ハンド・アセンブルしてマシン語コードに するところまで来ていたので、今回はその続きとして、 そのコードをファイルにして、実際に実行してみることにする。まず、コードをファイル化するために、 以前のブログ 『バイナリ・エディター「Stirling(スターリング)」』 で紹介した Windows用バイナリエディタ 「Stirling(スターリング)」 を使う。 そこで、新規ファイルを開いて、 マシン語コード「B2, 53, B4, 02, CD, 21, CD, 20」 を順番に打ち込んで行く。
入力が終了したら、 適当なディレクトリにファイルをセーブする。 ここでは、ファイル名を「disp1.com」としておこう。 ウィンドウズ上で、この手のプログラムを 実行するためには拡張子を「.com」とする必要がある。
さて、準備が完了したので、実際に実行してみよう。 ウィンドウズからコマンド・プロンプトを起動して、 それから 先ほどのファイル「disp1.com」を保存した ディレクトリへ「CD」コマンドで移動する。 例えば、デイレクトリ「C:\TEST」に移動するのであれば
cd C:\TESTとする。
そこで、単に、「disp1」とタイプしてからリターンキーを打てば
C:\TEST>disp1 S C:\TEST>のように、今回作成したマシン語プログラムが実行され、 アルファベット大文字の「S」が表示されてから 無事にプロンプトが戻ってくるハズだ。
たかが 文字を1文字 表示するだけのプログラムではあるが、 自分でマシン語を直接打ち込んだプログラムが きちんと動作してくれるとなんとも言えず嬉しいものだ。
【参考リンク】
カテゴリー: プログラミング 22:52 | コメント (0) | トラックバック (0)
2007年2月25日
8086マシン語、ハンド・アセンブル実験(1)
知り合いの方からマシン語についてのご質問を頂いたので、 一種のデモンストレーションとして 8086のマシン語をハンド・アセンブルしてみることにする。 但し、複雑なプログラムは大変なので、 最低限 マシン語が動作していることがわかるレベル、 ということで事前に指定した一文字を画面に表示させるプログラムを作ってみる。たった 一文字の表示であっても、 OSやBIOSに頼らず、全てをマシン語で組むのは非常に大変なので、 ここでは、安直にMS-DOSファンクションコールを呼ぶこととしよう。 これであればWindowsのコマンド・プロンプト画面、いわゆる「DOS窓」の中で実行できるハズだし、 もし、暴走してしまっても、その「DOS窓」を強制終了させれば、 Windows自体をリセットする必要もない。
ここでは、 「MS-DOS MASM プログラミング入門」 のページに MS-DOSファンクションコールについての解説があるのでそれを参考にしてみる。 これによると、出力に1文字出力するファンクションコールは、 「AH = 02H : DL = 出力する文字コード」となっている。 この情報をもとに アセンブラで記述してみると以下の4行になる。
mov dl, 53h ; 「S」の字の ASCII文字コード を DLレジスタにセット mov ah, 02h ; 出力に1文字出力するファンクションコールを指定 int 21h ; MS-DOSファンクションコール int 20h ; プログラムの終了これをIntel の 80x86系CPUのオペコード・テーブルを使って 16進数に変換してみる。
まず、1行目の「mov dl, 53h」について。 DL レジスタに1バイトの値をセットするオペコードは「B2」で、 それに引き続き、セットしたい1バイトの値が来る。 この例では、大文字の「S」の字を表示することとして、 そのASCIIコードである 53h が来ることになる。 よって、「mov dl, 53h」の行は16進コードの「B2, 53」となる。
同様に、2行目の「mov ah, 02h」の オペコードは「B4」で、このコードに引き続き、 出力に1文字出力する MS-DOSファンクションコール を表す 「02h」をセットする。 よって、「mov ah, 02h」の行は16進コード「B4, 02」となる。
それからファンクションコールを実行する ソフトウェア割り込みである「int」命令のコードは「CD」であり、 直後に割り込み番号を1バイトで指定する。 MS-DOSファンクションリクエストの割り込み番号は「21」なので 「int 21h」はコード「CD, 21」となり、 その直後の、プログラムの終了を意味する 「int 20h 」がコード「CD, 20」となる。
これらを全てつなげてみると 「B2, 53, B4, 02, CD, 21, CD, 20」 となる。
では、実際の実行方法については次回のブログへの続きとしよう。
【参考リンク】
カテゴリー: プログラミング 22:50 | コメント (0) | トラックバック (0)
2007年1月 3日
D言語
この「D言語」を開発しているのは 「Digital Mars社」で この会社は 多くのプラットホームに対する C/C++ コンパイラを提供してきている会社だ。 「D言語」の詳細については、 「Digital Mars社」 の 「D Programming Language」 ページにある。 また、すでに 日本語版のページができているし、 D言語を紹介する 「D言語パーフェクトガイド」 という書籍も発売されている。
日本語ページから 「D言語」の説明部分を引用させていただくと、
D はシステムプログラミング言語です。 CやC++の高いパフォーマンスと、 RubyやPythonのような現代的な言語が プログラマにもたらした生産性とを併せ持つことに焦点をあわせています。 特に、品質保証、ドキュメンテーション、管理、可搬性、信頼性 を 実現することに留意して設計されています。と説明されている。 また、ウィキペディア「D言語」では
C言語の後継としてはC++が有名であるがその複雑さも随一である。 Javaは複雑さを適度に押さえ、豊富な標準ライブラリを持つが、 仮想マシンを必要とするためパフォーマンスを求める場合には敬遠される。 かといってC言語では低レベルすぎるといった、 それぞれの言語の使いづらさに対して現実主義的な回答を模索した言語といえる。と説明している。 RubyやPythonのような 先進的なスクリプト言語の生産性と、 Javaよりも早い実行スピードを併せ持つ事を 目指したようなコンパイラ言語と言えるだろう。
言語仕様の具体的な説明として 「D vs その他の言語」 というページで、 C, C++, C#, Java とD言語の機能について比較しているので、 従来の言語から どこが改善されたのかが比較できるはずだ。
【参考リンク】
カテゴリー: プログラミング 22:39 | コメント (0) | トラックバック (0)
2006年11月 7日
ハンガリアン記法 (ハンガリー記法)
プログラミングにおける 「ハンガリアン記法」または「ハンガリー記法」と呼ばれる 命名法があるのだが、それについて調査してみた。プログラムを書く際、それも大規模なシステムを 複数のプログラマーが協力し合って開発する場合など、 変数名やクラス名などの名前の付け方が問題になることが多い。 その問題の解決方法のひとつとして、 名前の付け方、つまり命名方法を統一することが挙げられる。 そして命名手法のひとつに、「ハンガリアン記法」「ハンガリアン命名規約」 または「ハンガリー記法」「Hungarian Notation」と呼ばれる方法がある。
マイクロソフト(Microsoft) のプログラマである Charles Simonyi(チャールズ・シモニー)氏が発案したこの命名方法は 彼がハンガリー出身であるところから このように名づけられたそうだ。
この命名手法の主な特徴は、 変数の型を略して接頭文字(プレフィックス)として変数名に付加することである。 例えば、ポインタ変数であれば、その変数名「X」の最初に「p」をつけて「pX」とするとか。 この方法は、変数の型を宣言する必要のない言語では 変数名を見ただけで型がわかるので重宝かもしれない。
この「ハンガリアン記法」の関連サイトをいろいろ読んでみると、 以前は マイクロソフト(Microsoft)でも推奨されていたそうだが、 最近はそうでもないらしい。 変数の命名方法については、一概に何がよいとは言えないと思う。 これは開発言語にもよるだろうし、 また開発のスタイル、例えば、自分ひとりでプログラミングするのか、 それともグループでソースを共有するのか、 によっても最適な命名方法が変わってくると思う。
【参考リンク】
カテゴリー: プログラミング 22:21 | コメント (0) | トラックバック (0)
2006年10月18日
DeleteFolderメソッド問題の解決策(5)仮説実証編
DeleteFolderメソッド問題の記事が続いているが、 さらに最後にもうひとつ。前々回のブログ 「DeleteFolderメソッド問題の解決策(3) 仮説崩壊」 において、自分が立てた新たな仮説 「GetFolderメソッドによって抽出されたフォルダ名のインスタンスは、 DeleteFolderメソッドにより、そのフォルダが削除されるのと同時に削除される」が 正しいかどうか確認するスクリプトを書いてみた。
// // フォルダ削除実験スクリプト5 WSH(JScript) // // FileSystemObject オブジェクトの作成 var FSO = WScript.CreateObject("Scripting.FileSystemObject"); // GetFolderメソッドからフォルダ名を抽出 // 実際は、きちんとリストしないといけませんが // ここでは省略して最初に見つかったひとつのサブフォルダだけを扱います。 folderNameEnu = new Enumerator( FSO.GetFolder(".").SubFolders ); var DelFolderName = new String( folderNameEnu.item() ); // 削除前にフォルダ名の表示 WScript.Echo( "削除前の DelFolderName は " + DelFolderName + " です。"); WScript.Echo( "削除前の folderNameEnu.item() は " + folderNameEnu.item() + " です。"); // フォルダの削除 FSO.DeleteFolder(DelFolderName, true); // 結果の表示 WScript.Echo( "削除後の DelFolderName は " + DelFolderName + " です。"); WScript.Echo( "削除後の folderNameEnu.item() は " + folderNameEnu.item() + " です。");ご注意:このスクリプトを実行すると、カレント・フォルダの下にあるサブフォルダをひとつ、 実際に削除してしまいますので、お取り扱いには十分にご注意ください。
内容は単に、DeleteFolderを呼ぶ前後で、 folderNameEnu.item() の値を直接表示させて その内容を確認しているだけのことである。 これを結果がわかりやすいように コマンド・プロンプトから cscript で実行してみると
C:\WSH>dir /w Volume in drive C is WD2500 Volume Serial Number is D486-2A1E Directory of C:\WSH [.] [..] delete.js [test] 1 File(s) 860 bytes 3 Dir(s) 123,581,857,792 bytes free C:\WSH>cscript delete.js Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. 削除前の DelFolderName は C:\WSH\test です。 削除前の folderNameEnu.item() は C:\WSH\test です。 削除後の DelFolderName は C:\WSH\test です。 削除後の folderNameEnu.item() は です。 C:\WSH>dir /w Volume in drive C is WD2500 Volume Serial Number is D486-2A1E Directory of C:\WSH [.] [..] delete.js 1 File(s) 860 bytes 2 Dir(s) 123,581,857,792 bytes free C:\WSH>となった。 削除後の folderNameEnu.item() の表示だけが 空白になっている。 このことから 前述の仮説が正しいであろうと考えられる。
カテゴリー: プログラミング 22:03 | コメント (0) | トラックバック (0)
2006年10月17日
DeleteFolderメソッド問題の解決策(4) 改良版
ここまで、DeleteFolderメソッド問題の記事が続いているので ついでにもうひとつ。とりあえず問題解決となったブログ 『DeleteFolderメソッド問題の解決策(2)「new String」』 で示したスクリプトは 自分の目論見どおり動作しているが、 よくよく考えると、DelFolderName2 なんて変数を新たに準備する必要は全然なかったことがわかる。 その部分に変更を加えたのがこれ。
// // フォルダ削除実験スクリプト4 WSH(JScript) // // FileSystemObject オブジェクトの作成 var FSO = WScript.CreateObject("Scripting.FileSystemObject"); // GetFolderメソッドからフォルダ名を抽出 // 実際は、きちんとリストしないといけませんが // ここでは省略して最初に見つかったひとつのサブフォルダだけを扱います。 folderNameEnu = new Enumerator( FSO.GetFolder(".").SubFolders ); var DelFolderName = new String( folderNameEnu.item() ); // 削除前にフォルダ名の表示 WScript.Echo( "削除するフォルダは " + DelFolderName + " です。"); // フォルダの削除 FSO.DeleteFolder(DelFolderName, true); // 結果の表示 WScript.Echo( "削除したフォルダは " + DelFolderName + " です。");ご注意:このスクリプトを実行すると、カレント・フォルダの下にあるサブフォルダをひとつ、 実際に削除してしまいますので、お取り扱いには十分にご注意ください。
このスクリプトでは、 DelFolderName という文字列変数に folderNameEnu.item() から直接 new String してやっている。 そして、DeleteFolderメソッドにも 削除するフォルダ名として この文字列変数DelFolderNameを引数にしているが、 削除後でも、DelFolderNameの内容を表示することができている。 結局、削除フォルダ名を格納する文字列変数は1個あれば十分だったということだ。
カテゴリー: プログラミング 22:35 | コメント (0) | トラックバック (0)
2006年10月16日
DeleteFolderメソッド問題の解決策(3) 仮説崩壊
前回のブログで DeleteFolderメソッドを実行すると フォルダ名までも消されてしまう という問題について、とりあえずの解決方法に辿り着いた。 実はこの一連のブログを実際に書いてみて 新たに気付いたことがあったのでそれについてのレポート。自分のバックアップ・スクリプトをコーディングしている際に 出くわした この問題、 実際に前回のブログのような方法で解決させた。 そしてその結果、自分としては、 「DeleteFolderメソッドに引数で与えた文字列の内容(インスタンス)が 消されてしまうものだ」と思い込んでいた。 そのため、このことをレポートするブログを書くために、 当初、以下のような実験スクリプトを用いて解説するつもりだった。
// // フォルダ削除実験スクリプト 初期バーション WSH(JScript) // // FileSystemObject オブジェクトの作成 var FSO = WScript.CreateObject("Scripting.FileSystemObject"); // 削除するフォルダ名 // (実際はGetFolderメソッドから取得) var DelFolderName = "test"; // フォルダの削除 FSO.DeleteFolder(DelFolderName, true); // 結果の表示 WScript.Echo( "削除したフォルダは " + DelFolderName + " です。");ご注意:このスクリプトを実行すると、カレント・フォルダの下に「test」というサブフォルダある場合、 実際に削除してしまいますので、お取り扱いには十分にご注意ください。
このスクリプトでは、フォルダ名が決めうちされているので 実行するカレント・フォルダ下に 事前に「test」というサブフォルダを作成しておかなければならないが、 実際に実行してみた。 すると、フォルダ削除後にも関わらず、 フォルダ名が表示されてしまった。
ということは、自分が立てた 「DeleteFolderメソッドに引数で与えた文字列の内容(インスタンス)が 消されてしまうものだ」 という仮説が覆されてしまったわけだ。 それから 慌てて 元になったスクリプトを見直して 新たに実験スクリプトをいくつか書いて実験した結果 辿り着いた結論は 「GetFolderメソッドによって抽出されたフォルダ名のインスタンスは、 DeleteFolderメソッドにより、そのフォルダが削除されるのと同時に削除される」 ということだった。 それに基づいて書いた実験スクリプトが 以前のブログ 「DeleteFolderメソッドで フォルダ名も消える謎」 にあるスクリプトである。
カテゴリー: プログラミング 22:03 | コメント (0) | トラックバック (0)
2006年10月15日
DeleteFolderメソッド問題の解決策(2)「new String」
前回ブログからの続きで、 DeleteFolderメソッドを実行すると フォルダ名までも消されてしまう 問題の解決策 第2弾。消されるフォルダ名の控えを作っておくために 文字列変数を別の文字列変数に代入しただけでは、 いわゆる「参照渡し」になってしまい、 結局のところ文字列の実態はひとつしか存在していないので、 DeleteFolderメソッドによって その実態が消されてしまうと、あとには何も残っていないことになってしまう。
この問題を解決するためには、 完全な文字列のコピーを別のメモリ領域に作ってしまえばよいことになる。 そのための変更を前回ブログのスクリプトに加えたのがこちら。
// // フォルダ削除実験スクリプト3 WSH(JScript) // // FileSystemObject オブジェクトの作成 var FSO = WScript.CreateObject("Scripting.FileSystemObject"); // GetFolderメソッドからフォルダ名を抽出 // 実際は、きちんとリストしないといけませんが // ここでは省略して最初に見つかったひとつのサブフォルダだけを扱います。 folderNameEnu = new Enumerator( FSO.GetFolder(".").SubFolders ); var DelFolderName = folderNameEnu.item(); // 消されちゃうんであれば、もう一個 余計に準備しておく。 // 「参照渡し」にならないように 新たなオブジェクトを作成 var DelFolderName2 = new String( DelFolderName ); // 削除前にフォルダ名の表示 WScript.Echo( "削除するフォルダは " + DelFolderName2 + " です。"); // フォルダの削除 FSO.DeleteFolder(DelFolderName, true); // 結果の表示 WScript.Echo( "削除したフォルダは " + DelFolderName2 + " です。");ご注意:このスクリプトを実行すると、カレント・フォルダの下にあるサブフォルダをひとつ、 実際に削除してしまいますので、お取り扱いには十分にご注意ください。
このように「new」演算子を用いて 新たな String オブジェクト を作成してやるようにしてみた。 こうすると、フォルダ削除後にも、 そのフォルダ名を表示することができるようになった。
【参考リンク】
カテゴリー: プログラミング 22:20 | コメント (0) | トラックバック (0)
2006年10月14日
DeleteFolderメソッド問題の解決策(1) 「値渡し」と「参照渡し」
前回ブログからの続きで、 DeleteFolderメソッドを実行すると フォルダ名までも消されてしまう 問題の解決策を試してみる。ということで、前回ブログのスクリプトに変更を加えたのがこちら。
// // フォルダ削除実験スクリプト2 WSH(JScript) // // FileSystemObject オブジェクトの作成 var FSO = WScript.CreateObject("Scripting.FileSystemObject"); // GetFolderメソッドからフォルダ名を抽出 // 実際は、きちんとリストしないといけませんが // ここでは省略して最初に見つかったひとつのサブフォルダだけを扱います。 folderNameEnu = new Enumerator( FSO.GetFolder(".").SubFolders ); var DelFolderName = folderNameEnu.item(); // 消されちゃうんであれば、もう一個 余計に準備しておく。 var DelFolderName2 = DelFolderName; // 削除前にフォルダ名の表示 WScript.Echo( "削除するフォルダは " + DelFolderName2 + " です。"); // フォルダの削除 FSO.DeleteFolder(DelFolderName, true); // 結果の表示 WScript.Echo( "削除したフォルダは " + DelFolderName2 + " です。");ご注意:このスクリプトを実行すると、カレント・フォルダの下にあるサブフォルダをひとつ、 実際に削除してしまいますので、お取り扱いには十分にご注意ください。
これは DeleteFolderメソッドに対して、 引数として与えたフォルダ名の文字列が消されてしまうのであれば、 消される前に それを控えておけばよいであろうと、 ということで単に、
var DelFolderName2 = DelFolderName;の一行を加えてみた。 ところがその実行結果は前回と変わらず、やはり、 フォルダ名が消されてしまって、 フォルダ削除後のフォルダ名表示ができなかった。
この種の問題は いわゆる「値渡し」 と 「参照渡し」の問題で、 これについては、マイクロソフトの JScript ドキュメント「 JScript: データのコピー、受け渡し、および比較」に記載されている。 このページの説明によると「値渡し」とは
値渡しによるコピーや受け渡しでは、コンピュータのメモリ内に空間が新しく確保され、元の値がそこへコピーされます。 それぞれの値は別の値と見なされるため、値渡しした後で元の値を変更しても、コピーされた値に影響は及びません (逆の場合も同様です)。一方、「参照渡し」とは、
参照渡しによるコピーや受け渡しでは、実際に作成されるのは元の項目へのポインタですが、そのポインタを、あたかもコピーされた項目であるかのように扱うことになります。この場合は、元の項目に変更を加えると、元の項目とコピーされた項目の両方が変更されます (逆の場合も同様です)。実際存在する項目は 1 つだけで、"コピーされた項目" は、データへのもう 1 つの参照に過ぎません。と説明されている。 そしてJScript の文字列の場合は
文字列の場合は、コピーや受け渡しは参照渡しで行われますが、比較は値渡しで行われます。となっている。つまり JScriptにおいて 「=」を用いて 文字列変数に文字列変数を代入したとしても それは、元の文字列へのポインタがひとつ増えただけであり、 実際に存在する文字列はひとつしかないわけである。 そのため、今回 追加した一行は全くの無駄ということになってしまう。
【参考リンク】
カテゴリー: プログラミング 22:33 | コメント (0) | トラックバック (0)
2006年10月13日
DeleteFolderメソッドで フォルダ名も消える謎
前回ブログからの続きで、 WSHによるバックアップ・スクリプトの開発中に フォルダを削除する際にハマッタこと。実際に書いたバックアップ用のスクリプトはもっと長いのだが、 この フォルダの削除に関する失敗部分だけを抜き出して このブログで解説してみようと思う。
ここで私がプログラムしたいと思ったのは、 削除したフォルダの名前をログに記録しておくことだった。 ちなみに、WSHにおけるイベント・ログの作成方法については、 @ITの解説記事 「運用 Windows管理者のためのWindows Script Host入門」の アプリケーション・イベント・ログの作成 に詳しく解説してある。
以下のスクリプト例では、実験を簡単にするために、 GetFolderメソッドから得たフォルダ名の最初のひとつのみを扱っている。 実際に動作させているバックアップ・スクリプトでは きちんとリストにして全てのサブフォルダ名について処理している。 また、この例では イベント・ログに書き込む代わりに 画面に表示するように変更している。
// // フォルダ削除実験スクリプト1 WSH(JScript) // // FileSystemObject オブジェクトの作成 var FSO = WScript.CreateObject("Scripting.FileSystemObject"); // GetFolderメソッドからフォルダ名を抽出 // 実際は、きちんとリストしないといけませんが // ここでは省略して最初に見つかったひとつのサブフォルダだけを扱います。 folderNameEnu = new Enumerator( FSO.GetFolder(".").SubFolders ); var DelFolderName = folderNameEnu.item(); // 削除前にフォルダ名の表示 WScript.Echo( "削除するフォルダは " + DelFolderName + " です。"); // フォルダの削除 FSO.DeleteFolder(DelFolderName, true); // 結果の表示 WScript.Echo( "削除したフォルダは " + DelFolderName + " です。");ご注意:このスクリプトを実行すると、カレント・フォルダの下にあるサブフォルダをひとつ、 実際に削除してしまいますので、お取り扱いには十分にご注意ください。
で、このスクリプトを実行してみると 削除したかったフォルダは見事に削除されているのであるが、 削除後、そのフォルダ名が画面に表示されないのである。 どうも、DeleteFolderメソッドは、フォルダを削除した際に、 そのフォルダ名のインスタンスまでも削除してしまっているようだ。
削除前に、フォルダ名をログに書き込んでしまえば それで問題ないのだが、 自分としては、フォルダの削除が完了したことを確認してからログに記録したいと思った。 しかし、このように ファイル名がなくなってしまっては ログに書き込むこともできない。
次に、単純な解決方法を試してみたのだが それについては次回のブログで。
【参考リンク】
カテゴリー: プログラミング 22:52 | コメント (0) | トラックバック (0)
2006年10月12日
WSH での ファイルの操作方法
WSH で JScript を使って ファイルのバックアップを自動で行うスクリプトを書いていたのだが そこでの調査結果をまとめておく。今回 作ったバックアップ・スクリプトは 現在のフォルダを 別ドライブへ名前に日付をつけてコピーしておき、 何日か経って古くなった分は自動的に削除する、 といった仕様にしてみた。
WSH で ファイルやフォルダのコピーに関しては WSHの ファイルおよびフォルダをコピーする のページに解説してある。 この解説にもあるとおり、ファイルをコピーしたり等の ファイルの操作には、 FSO (File System Object) を使用する必要がある。 ともかく、ファイル操作をする前には、おまじないとして
var FSO = WScript.CreateObject("Scripting.FileSystemObject");というオブジェクトの作成をしておき、あとは
FSO.CopyFile("c:\\COMPlusLog.txt", "c:\\x\\");のように FSO オブジェクトのメソッド ひとつで ファイルのコピーが可能となる。 注意点としては、ファイル名の指定では、 英語環境ではバックスラッシュ「\」、日本語環境では円マーク「¥」を 2つ重ねないといけないということ。
フォルダ全体をコピーしたい場合も、 CopyFolder メソッド を使えば、簡単にフォルダ単位のコピーができてしまう。 今回の場合、ここで与えるコピー先のフォルダ名に現在の日付データを加えるようにしただけだ。
削除に関しても DeleteFile メソッド や DeleteFolder メソッド を利用すれば簡単にできてしまう。 ところが、削除すること自身には問題はなかったのだが、 それとは別の思わぬ 落とし穴にはまってしまった。 それは次回のブログとさせてもらおう。
【参考リンク】
- WSHにて ファイルおよびフォルダをコピーする
- FileSystemObject の概要
- CopyFile メソッド
- CopyFolder メソッド
- DeleteFile メソッド
- DeleteFolder メソッド
- @IT 第10回 WSHスクリプトからのファイル操作(1)
カテゴリー: プログラミング 22:52 | コメント (0) | トラックバック (0)
2006年10月11日
JavaScript で Right 関数
ちょっとした WSHスクリプト を JScript で書いていた際に、 文字列を右側から指定文字数だけ取り出す関数がほしくなった。マイクロソフトの「JScript」のページ から、それらしいメソッドを探したのだが、 文字列内の、指定位置からの指定された長さを持つ部分を返す substr メソッド とか、 文字列内の指定された位置にある文字列を返す substring メソッド とかは あるのだが、 文字列を右側から指定文字数だけ取り出すメッソドは見つからなかった。
VBScriptであれば、 Right 関数 というのがあって、単にこれを呼べばよいのだが、JScriptには存在していないようだった。 で、しょうがないので作ったのが以下の関数。
// // 文字列を右側から指定文字数だけ取り出す関数 // function right( str, n ) { l = str.length; if (n>l) n=l; return( str.substring(l-n,l) ); } strTest='ABCDEFG'; WScript.echo( strTest ); WScript.echo( right(strTest,3) );もっとクールなソリューションがあるのかもしれないが、 とりあえず動いているのでよしとしよう。
それにしても、今回の状況を考えると、 WSHでスクリプトを書く際は、 素直に 「VBScript」を使った方が幸せなのかもしれないと感じた。
【参考リンク】
カテゴリー: プログラミング 22:14 | コメント (1) | トラックバック (0)
2006年10月10日
WSH はどうやって言語を判断するのか?
昨日のブログで、WSHが wscript.exe や cscript.exe により 実行されているところまでわかった。 これらはデフォルトでも、VBScript と JScript という 2つの言語に対応しているのだが、 果たして どうやってそれらを見分けているのだろうか。 解析するために、簡単な実験を行ってみた。実験の準備として、
「Jtest.js」という名前を付けて
WScript.echo("Hello World!");
「Vtest.vbs」という名前を付けて
WScript.echo "Hello World!"
という2つのファイルを準備した。 これくらい短いプログラムでは、 違いとしては、関数の引数を括弧で囲むかどうかぐらいだ。
上記2つのファイルを ウィンドウズ・エクスプローラーから ダブルクリックすると、エラーもなく、「Hello World!」が表示される。 当たり前だが 全く同じ結果となる。
次に、それぞれのファイルの拡張子を 「Jtest.js」を「Jtest.vbs」に、 「Vtest.vbs」を「Vtest.js」に変更してみる。
前述と同じように、ウィンドウズ・エクスプローラーから ダブルクリックして、これら2つのファイルを実行してみると、 「Jtest.vbs」を実行させると 「Microsoft VBScript compilation error」というエラー表示が、 「Vtest.js」を実行させると、 「Microsoft JScript compilation error」というエラー表示になった。
このことから、wscript.exe や cscript.exe は 引数として与えられた実行ファイルの拡張子を見て、 どの言語として処理するべきかを判断していると 考えられる。
また、ついでに実験してみると、 「.js」の代わりに「.jse」、 「.vbs」の代わりに「.vbe」は利用できるようである。
カテゴリー: プログラミング 22:26 | コメント (0) | トラックバック (0)
2006年10月 9日
WSHの wscript.exe と cscript.exe とによる実行
昨日のブログでは JavaScript(JScript)を使って「Hello World!」を表示させてみたが、 その際、出来上がった「test.js」というファイルを ダブルクリックして実行してみた。 果たしてこのスクリプトを実際に実行しているのは何者なのだろうか?調べてみると、WSH を実行するには2つの方法があり、 それぞれに専用のコマンドが用意されている。 ひとつは「wscript.exe」で、もうひとつが「cscript.exe 」である。 その違いは 前者はGUIベース、後者はコンソール・ベース となっている。
通常、エクスプローラー上でダブルクリックした際には GUIベースの「wscript.exe」が実行されている。 その証拠に、今回作った「test.js」を エクスプローラからダブルクリックすると、 「Windows Script Host」というタイトルが付いた小さなウィンドウが開いて その中に「Hello World!」と表示された。
確認のためウィンドウズ・エクスプローラーの「ツール」メニューから 「フォルダ オプション(Folder Options)」を選んで 「ファイル タイプ (File Type)」タブをみてみると、 拡張子「.js」と「.vbs」のOpenアクションは 確かに「WScript.exe」にリンクされている。 また、「.jse」や「.vbe」も同様に「WScript.exe」に リンクされていることが確認できる。
一方、「cscript.exe 」を使ってコンソール・ベースで実行するためには コマンド・プロンプトに入って、そのファイルがあるディレクトリに行ってから
cscript test.jsとする。 すると、そのコマンド・プロンプト内で 上記コマンドに引き続き「Hello World!」とテキストで表示される。
【参考リンク】
- Windows ベースのスクリプト ホスト (Wscript.exe) を使用してスクリプトを実行する
- コマンド ライン ベースのスクリプト ホスト (Cscript.exe) を使ってスクリプトを実行する
- 運用 Windows管理者のためのWindows Script Host入門「第1回 WSHの内部構造」
カテゴリー: プログラミング 22:03 | コメント (0) | トラックバック (0)
2006年10月 8日
WSH による 「Hello World!」の表示プログラム
WSH を使った 最も基本的なプログラミングをしてみる。私も今までに いくつかのコンピュータ・プログラミング言語のお勉強をしてきたが、 その際のお決まりのプログラムが「Hello World!」と言う文字列を画面に表示する方法である。 今回も、この古き良き業界のしきたりにのっとって、 WSH で 「Hello World!」を表示してみることにする。
前のブログでも書いたとおり、 WSH では、VBScript と JavaScript(JScript) の 2つの言語処理系を備えいている。 巷の解説記事のほとんどは VBScript について書いてあるのだが、 あえてここでは、Jscript を使ってやってみる。
ノートパッドでも、TeraPad でも なんでもいいので、適当なテキスト・エディターを立ち上げて
WScript.echo("Hello World!");と打ち込み、または、上記の行をカット&ペーストしてから そのファイルに「test.js」という名前を付けて 適当なディレクトリ(ホルダー)に保存する。 打ち込む際は行末の「;」をお忘れなきように。
後は、ウィンドウズ・エクスプローラー(Windows Explorer)上で その「test.js」というファイルを ダブルクリックすると、 「Windows Script Host」というタイトルが付いた小さなウィンドウが開いて その中に「Hello World!」と表示されているハズである。
【参考リンク】
- VBScript & JScript プログラミングTips for WSH
- Wikipedia 「Hello world program」
- Windows Script Host「Echo メソッド」
カテゴリー: プログラミング 22:24 | コメント (0) | トラックバック (0)
2006年10月 5日
WSH (Windows Script Host)
ウィンドウズ(Windows)上での スクリプトの実行環境である WSH (Windows Script Host) についての調査記録。まず、「WSH (Windows Script Host)」とは、 ウィンドウズ(Windows)上でのスクリプトの実行環境であり、 言語としては JavaScript や VBScript で記述できる。 従来のバッチファイルによるバッチ処理機能と比較すると、もっと複雑な処理やGUIの利用が可能になっている。 バージョンに違いはあるにせよ、 Windows98以降の全てのウィンドウズに はじめからインストールされている機能である。
このWSHの関連記事が、アットマーク・アイティ には のように2つほど 収録されているようだ。 WSH を理解する上では 非常に参考になる。
では本家本元のマイクロソフト(Microsoft)からの情報としては、 が 最も基本的な情報ページのようだ。 また、前述のように、ディフォルトでは JavaScript(JScript) と VBScript の 2つの言語処理系を備えいているので、 それぞれの記述の方法については、 から辿ることができる。 そらから、スクリプトのサンプルとしては、 から参考となるコードを見つけることができるようだ。
【参考リンク】
- e-Words 「WSH (Windowsスクリプティングホスト)」
- @IT 「Windows管理者のためのWindows Script Host入門」
- @IT 「チェック式 WSH入門」
- マイクロソフトの「Windows Script」のページ
- マイクロソフトの「Windows Script Host」のページ
- マイクロソフトの「JScript」のページ
- マイクロソフトの「VBScript」のページ
- マイクロソフトの「Microsoft TechNet スクリプト・センター」
カテゴリー: プログラミング 22:23 | コメント (0) | トラックバック (0)