Spectre、Meltdown対策を完全にしてみる。

3日前にようやくSandy Bridge世代以降のSpectre、Meltdown対策のマイクロコード更新が始まったのにあわせて、(放置していた)PCのファームウェア更新をしてみた。

自宅ではこれに該当するのはIvy Bridge世代のDQ77MK、DQ77KBのインテルマザーベースのデスクトップPCとBroadwell世代のHP製i5ノートPC。自分が使っていないECSのSandy BridgeマザーベースのデスクトップPCはBIOS更新が2013年で止まって放置プレイで対象外。

DQ77MKマザーは2018年3月29日にインテルがリリースしたBIOSアップデート [MKQ7710H 86A] 0073を適用する。インテルマザーの常なのかBIOSアップデートがいつもながらうまくいかない。起動時F7キー押下ではIntel MEファームの更新で失敗する。BIOSリカバリーモードで更新するのは分解してジャンパーをいじる必要があって面倒なのでやりたくなかったが、なぜか3回同じF7操作を試したら更新がかかった。更新後デバイスマネージャをよく見るとプライマリNICを認識しておらず、BIOS設定のファクトリーリセットを行ったら回復してきた。

DQ77KBマザーも2018年3月29日にリリースされているBIOSップデート [KBQ7710H 86A] 0060を適用するのだが、これがドはまり。

・起動時F7キー押下でIntel ME Firmware更新がエラーで進まず。
・分解してリカバリーBIOSモードでは更新できたが、セカンダリNIC、WLANアダプタ(Wi-Fi 7260AC)を認識せず使えなくなった。温度、ファン回転数も取得できなくなった。起動時にシャーシイントリュージョンエラーが必ず出る。
・BIOS設定のファクトリーリセットを行ったが変わらず認識しない。
・もう一度ファームバージョン0060でFlash再書き込みしても変わらず。
・更新前のファームバージョン0059に戻したのにNIC、センサーとも回復しない。シャーシイントリュージョンも変わらず。
・バックアップ電池抜き、MBEXリセットとかやっても変わらない。
・Intel MEのファームを上書きで初期化したが特に変わらず。
半日ハマったorz…

結局次の手順でようやく各種デバイスの回復とファーム更新が完了。
ファームバージョン0053(KB0053P.BIO)をBIOSリカバリーモードで書き込んでNIC、センサー、WLANアダプタの認識とChassis Intrusionエラーが出ないことを確認。
・ファームバージョン0060(KB0060.BIO、最新のもの)にBIOSリカバリーモードで更新。

HPノートはメーカサイトから一番簡単そうなWindows EXE版のツールをダウンロードして更新。更新は特に問題なし。起動直後とかSSDのアクセスが多い時の動作が明らかに遅くなったorz…

更新前後で効果があるか確認した。DQ77MKの画面だが、他も同じ。

CPUの脆弱性「Meltdown」「Spectre」に関する状態を確認する – マイナビニュース
https://news.mynavi.jp/article/win10tips-247/

更新前
melt1

更新後
melt2

これであと5年戦える。MSはWin10サポート外のはずのSandyに手を打ってるし、Intelもサポート期限切れ製品なのに対応してくれたっていうのはえらいと思う。でもノートPCは明らかに遅くなったわ。

スペクターとメルトダウンから Windows デバイスを保護する
https://support.microsoft.com/ja-jp/help/4073757/protect-your-windows-devices-against-spectre-meltdown

KB4100347: Intel microcode updates
https://support.microsoft.com/en-us/help/4100347/intel-microcode-updates-for-windows-10-version-1803-and-windows-server

広告

Windows 8.1のDOS起動ディスクの中身の使い方。

Windows XP~8.1まであった機能、フロッピーフォーマット時の「MS-DOSの起動ディスクを作成する」オプション。Windows10で無くなったが、これでできるディスクの内容が日本人にとっては意味不明。英語が分からないとかじゃなくて、ファイルの内容が。

win81fd1

Windows MeのDOS部分が普通に起動できるのだが、
win81fd2

これらのファイルの使い道を知りたい。
win81fd3

ggrksると「IO.SYS、MSDOS.SYS、COMMAND.COM以外は要らないので消すべし。」みたいなのが出てきて疑問に答えてくれない。

実際にはこれらのファイルはフォントとキーボードレイアウトを各国仕様に変更するのに使う。フォーマット後のFDにできているCONFIG.SYSとAUTOEXEC.BATを適切に調整すれば自国で使ってる基本的な環境が整う状態になっている。もちろん国際化対応は日本も例外ではないが、2バイト文字フォントは入れられないのでキーボードだけの対応になる。具体的には次のようにCONFIG.SYS、AUTOEXEC.BATを修正する。

CONFIG.SYS

DEVICE=\DISPLAY.SYS CON=(EGA,437,6)

AUTOEXEC.BAT

MODE CON CP PREP=((437 850 852 860 863 865) \EGA.CPI)
MODE CON CP SEL=437
KEYB US,437,\KEYBOARD.SYS

これで表示に関してはmodeコマンドでmode con cp sel=850などコードページを437 850 852 860 863 865の中から切り替えて使える。キーボードはUS配列を指定しているので特に変わらず使えるが、KEYB HU,852,KEYBRD2.SYSでハンガリー用配列になるなど動的に切り替えができる。

win81fd4

外国語のこと知らんし っていう日本人向けおすすめ設定。これで日本語キーボードが使える。

CONFIG.SYS は0バイト(空)のまま。

AUTOEXEC.BAT

KEYB JP,437,KEYBOARD.SYS

AUTOEXEC.BATを作るだけ。フォーマット後にKEYB.COM、KEYBOARD.SYSはすでに入っているからグレーなサイトから持ってきたりする必要無し。KEYBOARD.SYSのJPはコードページ437、932の両方をサポートしているが表示側のJFONT.SYS、JDISP.SYSとフォントファイルが無いから、CP932はどうせ使えないので437を指定する。

CONデバイスのCP437を省略せずきちんと設定する場合はこんな感じ。これ以外のことはできないし、ここまで律儀に書く必要も無い。

CONFIG.SYS

DEVICE=\DISPLAY.SYS CON=(EGA,437,1)

AUTOEXEC.BAT

@ECHO OFF
MODE CON CP PREP=((437) \EGA.CPI)
MODE CON CP SEL=437
KEYB JP,437,\KEYBOARD.SYS

DOS起動ディスクの本来の使用用途は表示・キーボードの設定のためにCONFIG.SYSとAUTOEXEC.BATを作って、後はBIOS FLASHユーティリティをコピーしたらFDでPC起動してFLASHしてね、というのが正しい使い方なのだと思う。

16ビットWindowsプログラムをアセンブラしてみる。

アセンブラでWin16なWindowsプログラムを組んでみる。

リアルモード16ビットDOSのプログラムはいろいろ例が出てるのに、16ビットWindowsのプログラムは探してもほとんど無い。見つけてもINVOKEマクロで手抜きとか。ここではINVOKE無しで通常の呼出規約でAPIコールをする。ぱっと見はWin32に似ているが、結構違う。16ビットなのでレジスタの操作も16ビット単位。

これは前回のVS2017のmlとリンカではできなくてVisual C++ 6.0 SP5用のProcessor Packに入っているMASM 6.15を、リンカはVisual C++ 1.51に付いているものを使った。今のところMSDNで手に入る環境フルセットのMASM 6.11だけでもできると思う。

作成方法

ml msgbx16.asm /link libw.lib

msgbx16.asm

.model	small, pascal, nearstack
.386

MessageBox PROTO FAR PASCAL :WORD, :FAR PTR SBYTE, :FAR PTR SBYTE, :WORD


.code
sStart:
	sub	sp, 4
	
	push	word ptr 0
	push	ds
	push	offset strMsg
	push	ds
	push	offset strCapt
	push	word ptr 40h
	call	far ptr MessageBox

	mov	ax, 4c00h
	int	21h


.data
strCapt	db 'msgbx16', 0
strMsg	db 'Hello World !', 0


.stack
	db	100 dup (0)


	end	Start

動作はVMware上のWindwos2000Pro。

masmwin

VS2017のml.exe、ml64.exeを使ってみる。

アセンブラでWindowsのプログラムってどうやったらできるのかな? って思った。ずっと前にMASM32とか調べたら高機能マクロで簡単にできるよとか書いてあって、そんならCでやるわってなってから放置してた。

VS2017に付いてるml.exe(14.13.26132.0)の32ビット版でMessageBoxAを叩いて終わるだけのもの。これでも一応APIの呼び方は分かる。スタックに押し込んでAPIをコール。

msgbx.asm

.model	flat, stdcall

extern	MessageBoxA@16 : proc
extern	ExitProcess@4 : proc

public Start

.code
Start:
	push 40h
	push offset strCapt
	push offset strMsg
	push 0
	call MessageBoxA@16

	push eax
	call ExitProcess@4

.data
strCapt	db 'msgbx', 0
strMsg	db 'Hello World !', 0

end

アセンブルとリンクはml一行で完結。

ml msgbx.asm /link /subsystem:windows /Entry:Start kernel32.lib user32.lib

devenv.exe msgbx.exeでデバッグ。debugやsymdebと同じtやpやrコマンドが使える。

msgbx-devenv

64ビット版も作った。FASTCALL規約でAPIの引数がスタックではなくてレジスタを使う。

msgbx64.asm

extern	MessageBoxA : proc
extern	ExitProcess : proc

public	Start

.code
Start:
	sub rsp, 8h
	
	mov rcx, 0
	lea rdx, strMsg
	lea r8, strCapt
	mov r9, 40h
	call MessageBoxA

	mov ecx, 0
	call ExitProcess

.data
strCapt	db 'msgbx64', 0
strMsg	db 'Hello World !', 0

end
ml64 msgbx64.asm /link /subsystem:windows /entry:Start kernel32.lib user32.lib

Windows 10 EnterpriseをApril 2018 Update(1803)してみる。

ノートPCで使っているVL版(ボリュームライセンス版)のWindows 10 Enterprise、1703なので先日出た1803に更新してみる。

前回のFall Creators Update(1703)それ以前のCreators Updateと比べて、今回は超簡単だった。スタート→設定→更新プログラムのチェック。あとは完了まで若干の操作を除いて放置するだけ。約1.5時間。

Win10EntUpd1803

で終わったところ。前回見た「お使いのPCは監視され、…」の表示は無くなった。

Win10Ent1803-1

Win10Ent1803-2

今回もちょっと不具合。

・スキャナのユーティリティEPSON SCANが消えた。前回も、前々回も発生したのと同じ症状。EPSON SCANを再インストールして復活。読み取り設定などは消えずに残っていた。

・Synapticsのトラックパッドが使えなくなった。今回初めて。Win+X→デバイスマネージャ→マウスと他の…からSynaptic PS/2…を関連ファイルごと削除→再起動で自動的に再認識。設定→デバイス→マウス→その他のマウスオプションを開くと新しいツールのセットアップが始まった。

不具合はこれくらいだった。細かいところがいろいろ変わってる。表示切替時の効果が早くなった(アニメーションが完了するまでの時間が短くなった)気がするが気のせい?

『インサイド Visual InterDev』を読んだ。

ASPとVisual InterDevをいまさらちゃんと知りたくなったので『インサイド Visual InterDev』を古書で買ってきた。この本はアマゾンの英語版のレビューも「最悪!」っていう感じで書かれてるから、よっぽどひどいのだろう。今回読んだのはもちろん日本語版だが同じように感じた。

vid-ms1

「マイクロソフト公式解説書」シリーズって微妙で、詳しすぎてわけわからんすぎるか、とんでもない良書か、そうでなければただのウォークスルー・製品・新機能紹介。この本は後者。今更クラシックASPってのもどうかと思うが、なんでかASP.netな現在も「ASP最高!」ていう人もいるようで、ほーんそんなにええんかーと思ったのが起因。VIDがまだ現役だったころのウェブサイトといえばLAMP(Linux+Apache+MySQL+Perlとかの構成)がはやりだったが、個人的に管理してたイントラサイトはWIOP (Windows+IIS+Oracle+JSP)という変態構成だった。Windows ServerやOracleが比較的自由に使えたことと、MySQLとPHPが嫌いなことと、Linuxは他に使える人が居ないという理由で。MSのプロダクトはLinuxより好みだが、でもASPは「ダメなテクノロジー」と考えてたから使わなかった。

今回はVMWare14上にWindows NT 4.0 Workstation SP6にVisual Studio 97をセットアップして動作を確認した。すごくシンプルな感じで確かに「(ASP.netにはついてけないから)ASP最高!」になるのも分からなくも無いと思った。

vid-ms2

本の帯に「VB,VJ++を両方使いたいならコレ!!」って書いてあるからVJ++も使うんかと思ってわくわくしてたけど「VJと同じIDEが使える」とか「VJのプロジェクトも含めることができる」とかそういうことしか書いてない。サンプルプロジェクトもサンプルコードの1つも無し。この本ではVJ++は全然使えるようにならない。VBは「VBあればDesign-Time Control作れる」って書いてあってサンプルが載ってるけど「インターフェース」やら「コントロール」やらさらっと出てきて、この本だけではたぶん無理。しかもちゃんとやろうとすると(VB CCEでがんばるのでなければ)VB5 Professional以上が要るし、Design-Time Control SDKなんてのを追加で入れないといけないしで結構しんどい。しかもDesign-Time Control SDKは今は公開されておらず、MSDNサブスクライバダウンロードで「Web Control SDK and DDKs」という名で入手できたからMSDN入っててよかったと心底思った。この帯は「VBScript,JScriptを両方使いたいなら」を書き間違えたんだろう。

Web系・オープン系な人ですらもはや知らない人が多い気がする自称高機能Web開発環境Visual InterDev。この本はVisual InterDev 1.0がターゲットでこの環境もたいがいひどい。Visual Studio 97の開発環境とは言ってるが、オートコンプリートはおろかWYSIWYG編集もほぼできないしデバッガ機能も無いしできないことはFrontPageやその他のツールに丸投げ。自動FTP機能付きマルチファイルテキストエディタっていうくらいのが良い。もっと高機能なVisual InterDev 6.0は持ってるけどあえて使わないプレイ。

今更ASPでなんかしようというのは、いろいろ無理ゲーだとわかった。「(レガシー|クラシック)ASP最高!」と今から始めようとするのはよした方がいい。すでにMS含めてウェブ上の資料もかなり消滅してるし、ASPがダメだったのは歴史が証明している。

Advanced Windows 改訂第3版を読んだ。

Advanced Windows 改訂第3版を読んだ。

AdvWin3

Windows95が普及しきった時期に買って、第二章で挫折してから放置してた。よく似た装丁のプログラミングWindows95プログラミングWindows95 with MFCはどうにかこなしたが、これは無理だった。

あらためて読み返すとそこまで実はそこまで難しくは無い。16ビットから32ビットへ移り変わった時期の内容だが、Win16の知識がWin32プログラミングの役に立つのと同じように、現在でも十分通じる部分も多い。序章と第1章でWin32の概要説明が終わると、第2章でいきなり「カーネルオブジェクト」の解説が始まる。この構成が挫折の要因。第2章「カーネルオブジェクト」から第6章「仮想メモリの探求」までスキップして、第7章「アプリケーションでの仮想メモリの活用方法」から読み始めると最後まではこれまでに経験済みの内容やそれに関連した項目が多くて平易に読める。第18章「プロセス境界の突破」はまだ満足には理解できてない。

Windowsというかパソコンは「使ってれば分かるようになる」なんて言われるけど、それは単に使い方や表面上だけのお話。この本に載ってるようなカーネルオブジェクト、プロセス、メモリマネージャの動作、スレッド同期メカニズム、例外処理機構など「パソコンを使ってる」だけで知ることなんて絶対不可能だと思った。非プログラマーの感想としては、自作PCでOSのインストールができるとか、ExcelでVBAマクロが組めるとかのスキルも結構だが、こういった内容はギークの教養として知ってて損は無い(と思う)。

このシリーズ今は第5版まで出てて改訂第3版はアマゾンにも在庫が無いくらい古いが、他の二冊とあわせてもっと早く読み終えておくべきだった。この版はWindows NT4向けに書かれているがWindows95のこともちゃんと書いてあってちょっと得した感じ。64ビットWindowsが普及しきった現在、本当は第5版で64ビットのこともちゃんと勉強しないといけない。

MSプレスの本3冊読んで、ちょっとパソコンに詳しくなれたよ。

Googleの勧めるWindows 10 Pro Professional

Googleのスポンサー広告が完全に詐欺なソフト販売業者をサジェストしてきた。

outlaw

こういうふざけた出所がGoogleの豊富な資金になっていると思うと腹立たしい。精査とかザルなんかな。AdWordsの不適切な何とかのリンクを押した。

Windows 10 Pro Professionalってなんやねん。

DEBUG で クワイン その2

DEBUG (DEBUG.COM、DEBUG.EXE) で Quine その2。自分自身を出力するプログラムのx86アセンブラ版。

前回でクワインはできたが、標準出力だとリダイレクトするとDEBUG自身の出力がゴミになる。そのままでもエラーを無視すれば動かなくも無いが気持ち悪いし、標準エラー出力にするとリダイレクトできるのはNT系32ビットのCMDに限られて、DOSでは動かしにくいしであまり面白くない。クワインなら一発で自分自身を吐き出してほしい。

そこで結果は標準出力ではなくファイルに出力するようにした。ついでに「『自分自身を出力するプログラム』を出力する」機能も追加した。通常アセンブラで開発、デバックするときは次の手順になるが、

ソースコード→アセンブル→バイナリ→デバッグ

これだと

無→デバッグ→バイナリ+ソースコード

という意味不明なことになる。

クワインのコード(DEBUG.COMのレスポンス)

f100 630 0      
a100            
mov ah,3c       
mov cx,0        
mov dx,1a6      
int 21          
mov ax,3d01     
int 21          
jnc 113         
int 20          
mov bx,ax       
mov si,1c0      
mov di,40       
mov ah,40       
mov cx,10       
mov dx,si       
int 21          
mov ah,40       
mov dx,1a4      
mov cx,2        
int 21          
add si,10       
dec di          
jnz 11b         
mov si,1c0      
mov di,47       
mov ah,40       
mov dx,1a0      
mov cx,4        
int 21          
mov ah,40       
mov dx,si       
mov cx,10       
int 21          
mov ah,40       
mov dx,1a3      
mov cx,3        
int 21          
add si,10       
dec di          
jnz 13a         
mov si,5c0      
mov di,7        
mov ah,40       
mov cx,10       
mov dx,si       
int 21          
mov ah,40       
mov dx,1a4      
mov cx,2        
int 21          
add si,10       
dec di          
jnz 163         
mov ah,3e       
mov dx,1a6      
int 21          
int 20          
                
a1a0            
db"db ",27,d,a  
db"quout.txt",0 
                
a1c0            
db 'f100 630 0      '
db 'a100            '
db 'mov ah,3c       '
db 'mov cx,0        '
db 'mov dx,1a6      '
db 'int 21          '
db 'mov ax,3d01     '
db 'int 21          '
db 'jnc 113         '
db 'int 20          '
db 'mov bx,ax       '
db 'mov si,1c0      '
db 'mov di,40       '
db 'mov ah,40       '
db 'mov cx,10       '
db 'mov dx,si       '
db 'int 21          '
db 'mov ah,40       '
db 'mov dx,1a4      '
db 'mov cx,2        '
db 'int 21          '
db 'add si,10       '
db 'dec di          '
db 'jnz 11b         '
db 'mov si,1c0      '
db 'mov di,47       '
db 'mov ah,40       '
db 'mov dx,1a0      '
db 'mov cx,4        '
db 'int 21          '
db 'mov ah,40       '
db 'mov dx,si       '
db 'mov cx,10       '
db 'int 21          '
db 'mov ah,40       '
db 'mov dx,1a3      '
db 'mov cx,3        '
db 'int 21          '
db 'add si,10       '
db 'dec di          '
db 'jnz 13a         '
db 'mov si,5c0      '
db 'mov di,7        '
db 'mov ah,40       '
db 'mov cx,10       '
db 'mov dx,si       '
db 'int 21          '
db 'mov ah,40       '
db 'mov dx,1a4      '
db 'mov cx,2        '
db 'int 21          '
db 'add si,10       '
db 'dec di          '
db 'jnz 163         '
db 'mov ah,3e       '
db 'mov dx,1a6      '
db 'int 21          '
db 'int 20          '
db '                '
db 'a1a0            '
db 'db"db ",27,d,a  '
db 'db"quout.txt",0 '
db '                '
db 'a1c0            '
db '                '
db 'n quin.com      '
db 'r cx            '
db '530             '
db 'w               '
db 'g               '
db 'q               '
                
n quin.com      
r cx            
530             
w               
g               
q               

第一世代のジェネレータ(perlのコード)

#!perl

# DEBUG.COM用 クワイン ジェネレータ 2

# ソース前半部	(コメント中の”’はSBCS)
$part1 =<<EOT;
f100 630 0		# ごみ消去
a100
mov ah,3c		# DOSコール番号 空のファイル作成
mov cx,0		# 属性
mov dx,1a6		# ファイル名のアドレス
int 21			# DOSコール
mov ax,3d01		# DOSコール番号 ファイルオープン、書き込みモード
int 21			# DOSコール
jnc 113			# 成功したら続行
int 20			# 失敗したら終了
mov bx,ax		# 出力ハンドル。DOSコールでは不変なのでストアは1回だけ。stderrの場合は2にする。
mov si,1c0		# -- フェーズ1:実行ソース表示。埋め込みソース開始アドレス->SI (SIは表示文字列のポインタ)
mov di,40		# 64行が対象。残り7行は後半部になる。(DIは減算カウンタ)
mov ah,40		# DOSコール番号 ファイル出力
mov cx,10		# 1行は固定長16文字
mov dx,si		# 表示文字列アドレスをDXにセット
int 21			# 表示する
mov ah,40		# DOSコール番号 ファイル出力
mov dx,1a4		# CRLF文字列アドレス
mov cx,2		# 長さ2文字
int 21			# 表示する
add si,10		# 表示文字列ポインタSIを1行分(16文字)進める
dec di			# 行数カウンタデクリメント
jnz 11b			# 指定行数表示したらループ終了
mov si,1c0		# -- フェーズ2:埋め込みソース表示。ソースはDB ’...’ で囲む。SIは表示文字列のポインタ。
mov di,47		# 71行が対象。(全行)
mov ah,40		# DOSコール番号 ファイル出力
mov dx,1a0		# 文字列 ”DB ’” のアドレス
mov cx,4		# 長さ4文字
int 21			# 表示する
mov ah,40		# DOSコール番号 ファイル出力
mov dx,si		# 表示文字列アドレスをDXにセット
mov cx,10		# 1行は固定長16文字
int 21			# 表示する
mov ah,40		# DOSコール番号 ファイル出力
mov dx,1a3		# 文字列 ’CRLF のアドレス
mov cx,3		# 長さ3文字
int 21			# 表示する
add si,10		# 表示文字列ポインタSIを1行分進める
dec di			# 行数カウンタデクリメント
jnz 13a			# 指定行数表示したらループ終了
mov si,5c0		# -- フェーズ3:後半部ソース表示。
mov di,7		# 7行が対象
mov ah,40		# DOSコール番号 ファイル出力
mov cx,10		# 1行16文字
mov dx,si		# 表示文字列アドレスをDXにセット
int 21			# 表示する
mov ah,40		# DOSコール番号 ファイル出力
mov dx,1a4		# CRLF文字列アドレス
mov cx,2		# 長さ2文字
int 21			# 表示する
add si,10		# 表示文字列ポインタSIを1行分進める
dec di			# 行数カウンタデクリメント
jnz 163			# 指定行数表示したらループ終了
mov ah,3e		# DOSコール番号 ファイルクローズ
mov dx,1a6		# ファイル名のアドレス
int 21			# DOSコール
int 20			# 終了のDOSコール
			# a100コマンド終了の合図
a1a0			# 「エスケープ文字列」”db ”, ”,CR,LF の格納場所
db"db ",27,d,a	# CRLFだけの出力にも使う
db"quout.txt",0	# 出力ファイル名
			# a200コマンド終了の合図
a1c0			# 埋め込みソースの格納場所。次の行からがdb ’...’のプレースホルダになるが、同じなので中身は無し。
EOT

# ソース後半部
$part2 =<<EOT;
			# a300コマンド終了の合図
n quin.com		# 実行ファイル生成時(wコマンド)のファイル名指定
r cx			# ファイルサイズは 600h バイト
530
w			# ファイルに書き込み
g			# 実行コマンド
q			# 終了コマンド
EOT

# #
$part1 =~ s/#.+?\n/\n/g;
$part2 =~ s/#.+?\n/\n/g;

$part1 =~ s/[  \t]+?\n/\n/g;
$part2 =~ s/[  \t]+?\n/\n/g;

print $part1;
@escp = split(/\n/, $part1.$part2);
foreach $itr (@escp) {
	$line1 = "db '".$itr;
	$line2 = " "x (20-length($line1))."'\n";
	print $line1.$line2;
}
print $part2;

実行結果

DOSKEYでマルチコマンド実行。Q1.TXTはジェネレータが生成した第一世代のコード。セマンティクスは同じだが余分な空白が無いので第一世代だけは第二世代以降とは若干異なる。
quin_dbg2-1

Q2.TXTは第二世代のコード、QUOUT.TXTは第三世代のコード。
quin_dbg2-2

コード(DEBUGのレスポンス)をDEBUGにかけるとファイルを2個生成する。自分自身はQUOUT.TXTに、自分自身生成プログラムはQUIN.COMに出力する。そしてQUIN.COMを実行するとQUOUT.TXTを生成する。これも前世代と同じ内容になる。(何を書いているかよくわからなくなった。)
quin_dbg2-3

 

DEBUG.COM の wコマンドがポイントで、あらかじめBX、CXにサイズをセットしておくとnコマンドで指定したファイルにCS:100hか指定アドレスからBX、CXにセットされた長さだけバイナリで保存する。これでメモリイメージを保存できる。

書式
w [セグメントアドレス:オフセットアドレス]

機能
セグメント:オフセットアドレスから (BX << 16 | CX)バイト書き込む。アドレス未指定なら CS:0100h が先頭。

DEBUG で クワイン。

DEBUG で Quine。

かつてDOSで標準装備されて今も32ビット版のWindowsについている DEBUG.COM (DEBUG.EXE)で Quine を書いた。やってることはMASMでクワインと同じ。書き直してるのでちょっとはマシかも。

・quin.txt

a100
mov bx,1
mov si,300
mov di,33
mov ah,40
mov cx,10
mov dx,si
int 21h
mov ah,40
mov dx,204
mov cx,2
int 21h
add si,10
dec di
jnz 109
mov si,300
mov di,36
mov ah,40
mov dx,200
mov cx,4
int 21
mov ah,40
mov dx,si
mov cx,10
int 21h
mov ah,40
mov dx,203
mov cx,3
int 21h
add si,10
dec di
jnz 128
mov si,630
mov di,3
mov ah,40
mov cx,1
mov dx,si
int 21h
mov ah,40
mov dx,204
mov cx,2
int 21h
add si,10
dec di
jnz 151
int 20h

a200
db"db ",27,d,a

a300
db 'a100            '
db 'mov bx,1        '
db 'mov si,300      '
db 'mov di,33       '
db 'mov ah,40       '
db 'mov cx,10       '
db 'mov dx,si       '
db 'int 21h         '
db 'mov ah,40       '
db 'mov dx,204      '
db 'mov cx,2        '
db 'int 21h         '
db 'add si,10       '
db 'dec di          '
db 'jnz 109         '
db 'mov si,300      '
db 'mov di,36       '
db 'mov ah,40       '
db 'mov dx,200      '
db 'mov cx,4        '
db 'int 21          '
db 'mov ah,40       '
db 'mov dx,si       '
db 'mov cx,10       '
db 'int 21h         '
db 'mov ah,40       '
db 'mov dx,203      '
db 'mov cx,3        '
db 'int 21h         '
db 'add si,10       '
db 'dec di          '
db 'jnz 128         '
db 'mov si,630      '
db 'mov di,3        '
db 'mov ah,40       '
db 'mov cx,1        '
db 'mov dx,si       '
db 'int 21h         '
db 'mov ah,40       '
db 'mov dx,204      '
db 'mov cx,2        '
db 'int 21h         '
db 'add si,10       '
db 'dec di          '
db 'jnz 151         '
db 'int 20h         '
db '                '
db 'a200            '
db 'db"db ",27,d,a  '
db '                '
db 'a300            '
db '                '
db 'g               '
db 'q               '

g
q

32ビット版Windowsならコマンドプロンプト内で起動してるdebug.comにコピペでも流し込めるが106/109キー配列だと文字化けするので”を*に、’を:に置換するとうまく動く。それでもsymdebと違ってリダイレクトできないし、逆スクロールもできないからちゃんと動いてるのかわかりにくい。コマンドラインでリダイレクトを使って

debug < quin.txt > q2.txt

てやるとq2.txtに結果が保存される。要らないメッセージやエコーバックも保存されのでそこは手動で削る。結果は標準出力でなくファイルに保存したほうがよいかも。32ビット版のWindowsなら標準エラー出力に変更して2>&1でリダイレクトとすると出力を削らなくてもソースを取得できる。

quindebug

※ジェネレータは冗長なので削除。Ver2に載せる。

debugでquineなんて変人の仲間入りになるかと思ったが、アセンブラで素直に書くと正直わかりやすすぎる。全く難解プログラミングな感じがしない。RubyやCのクワインのほうがずっとわかりにくいし、わかりにくく書ける。