開局した後に必要な準備

アマチュア無線局免許が届いて無事に開局が終わりました。友達と無線で話したりする分にはこれで十分ですが、不特定の誰かと話すためにCQに応答したり、CQを発信するにはまだ用意する物があります。
・QSLカードを用意する
他のアマチュア無線局と交信した時に記念に交換するカードです。いくつかの交信条件を満たした無線局に贈られるアワードの申請には、相手からQSLカードを発行してもらう必要があります。逆にそういう目的を持った無線局と交信した時にはQSLカードを送らないとマナー違反になってしまうのです。
自宅のプリンタで印刷しても構いませんが、QSLカードにはいくつかの決まりがあります。サイズは長辺14~15cm、短辺9~10cmです。重量2g以上、4g以下です。一般的なコピー用紙など薄い紙では認められません。140g/㎡~260g/㎡の厚紙が必要です。官製はがきが丁度このサイズ、重量です。探せば郵便番号などの為のマスが印刷されていない用紙があるので、これらを利用すると良いでしょう。QSLカードの用紙に使えそうな製品を集めてみました。
Amazonで無地のはがきサイズ用紙を買う。
・JARLに入会する
QSLカードを交換するには、QSLビューローと呼ばれる機関を経由するのが一般的です。日本では日本アマチュア無線振興協会(JARL)がQSLビューローを兼ねているので、QSLビューローを使うためには入会しなくてはなりません。
QSLビューローを使えば相手のコールサインさえ分かれば、住所などが分からなくてもQSLカードを送る事が出来ます。QSLビューローを仲介せずに送っても構わないのですが、今の時代は他人に住所を教えるのは何かと抵抗がありますからね。
複数のQSLカードをまとめて発送する事も出来るので、件数が多い場合には個別に発送する場合よりも安く上げる事ができます。これは相手からQSLカードを貰う場合にも言えるので、QSLカードを集めてみるつもりがあるならJARLに入会しましょう。
・ログブック(業務日誌)を準備する
JARLの専用用紙でも、市販の専用用紙でも、普通のノートでも、Excelでも、専用ソフトでもよいのですが、交信内容を記録する物を用意しましょう。通信相手のコールサイン、交信日時、通信状況、使用周波数、電波形式などを記録しておきます。QSLカードの発行状況管理などにも使います。
Turbo HAMLOGというソフトが歴史も古く、結構メジャーのようです。
CQ出版社が発売している市販の専用用紙としてはこちらが入手しやすいでしょう。

アマチュア無線を始めるまで

ふと思い立ってアマチュア無線の免許を取ろうとしてみたものの、インターネットよりはるかに古い世界であるせいなのか、意外に「まったく知らない人向け」の情報というが少ない気がする。なので、自分で無線の世界に入りながら、ちょっとずつまとめていこうと思う。
アマチュア無線を始めるためには、まず以下のステップを踏まなきゃならない。なんとアマチュア無線を始めようと思ってから、実際に法的手続きが完了するまで最長で半年も、最短でも一ヶ月かかるのです。
1.従事者免許取得
1.1.国家試験を受ける方法
1.1.1.第四級アマチュア無線技士試験申し込み
財団法人日本無線協会(JRI)が全国各地でおこなっている国家試験に申し込みます。主要都市ならほぼ毎月、それ以外でも年に数回行われています。試験を受けようと思う月の前々月の20日までに申し込みをおこないます。申込書は各地の無線機器屋さん、大型書店で購入できます。アマチュア無線参考書の巻末に閉じ込められている事も多いです。
毎月第三日曜日に日本無線協会本部で行っている試験だけは例外で、試験日当日に窓口で受験の申込みをすませ、その日のうちに試験、結果発表、従事者免許申請発行まで行えます。早く欲しいと言う方や東京近郊の方はこれを利用すると良いです。
1.1.2.第四級アマチュア無線技士試験受験
第四級アマチュア無線技士試験は全部四択で法規12問、工学12問の系24問出題されます。法規、工学、それぞれ8問以上正解すれば合格です。試験時間は1時間ですが、15分くらいで解き終わると思います。前日に過去の問題などを一夜漬けすれば十分に合格できます。小学生低学年でも合格するような内容の試験ですが、引っかけ問題や計算問題も含まれるため、大人でも油断していると落ちますよ。
受験番号は、このあと従事者免許の申請に必要になるので無くさないでください。
1.1.3.第四級アマチュア無線技士合格通知
試験から約一ヶ月たつと合格通知が送られてきます。ですが、これは免許証でもなく、合格証書でもなく、ただの合格通知です。この後、無線従事者免許申請をおこなって、初めて免許証が送られてきます。
1.1.4.無線従事者免許証申請
アマチュア無線技士試験に合格したら、こんどは無線従事者免許証交付申請をおこないます。日本アマチュア無線連盟(JARL)が無線従事者免許証交付申請の代行業務をおこなっていますが、総務省に直接おこなっても手間があまり変わりません。代行業務だと2,200円、直接手続きすれば1,750円なので直接手続きしましょう。
無線従事者制度のホームページから申請用紙(PDF形式)をダウンロードして必要事項を記入の上、印紙をはりつけ、管轄の総合通信局に郵送するだけです。返信用封筒と住民票を同封するのを忘れないようにしましょう。
1.1.5.無線従事者免許証交付
無線従事者免許交付申請から約一ヶ月で免許証が送られてきます。
1.2.講習会を受ける方法
全国各地で行われている講習会を受けて免許を貰います。全国各地で年に1~2回程度おこなわれています。講習後の合格率は99%程度と、ほぼ落ちる人は居ないです。講習は二日間かけて行い、料金は二万円以上かかります。でも一夜漬けで十分受かるので、国家試験を受ける方法のほうが良いと思いますよ。
どちらかというと、アマチュア無線がメインではなく、何か別の目的のためにアマチュア無線を使おうと考えている人に向けたもののようです。たとえば登山とか、パラグライダーとか、レジャーボートとかですね。これらを楽しむ人にとって無線は文字通り命綱ですし、業務ではないからアマチュア無線の要件に入りますしね。
Amazonで試験に必要な物を買う。
2.無線局免許取得
2.1.無線機器購入
従事者免許証が届いたら無線機器を購入します。従事者免許がなくても、電波を出してはいけないだけで、無線機器を購入できないわけではないのですが、良心的なお店だと従事者免許を持たない人に売るのを嫌がります。だから受かってから買いに行こう。
基本的に何処で買ってもよいのですが、出来たら地元で無線機器を扱っているお店を探してみてください。その手のお店は、店主自身もアマチュア無線を楽しんでいる事が多いので、色々と教えてくれるでしょう。
それに、実は何処で買ってもあまり値段が変わらないんですよ。TVのように家電量販店が何千台とまとめて購入するのであれば、メーカーの卸値も安くなって値段の差も付くでしょう。ですがアマチュア無線はニッチな市場なので秋葉原の大きめの量販店でも、それほど大量に扱っているわけではないのです。卸値がほとんど変わらない以上は、何処でかっても同じ値段になってしまいます。
よくオークションなどで技適をとっていない無線機器を販売していますが、これらは買わないでください。無線局開局申請を行うときに、技適の取得を自分でおこなわなくてはならないため、ほぼ開局できなくなります。
2.2.無線局開局申請
無線機器を購入したら、アマチュア無線局開局申請書を出します。申請書には無線機器に書かれている適合証明番号を書かなくてはならないため、無線機器を購入しないと開局申請を出せません。
書き方が良くわからなければ、無線機を購入したお店で聞いてください。
無線機器の電源を入れても構いませんが、まだ無線局免許を貰っていないので、応答できません。電波を発信したら違法です。無線を聞きながら、無線局免許が届くのを気長に待ちましょう。
2.3.無線局免許交付
無線局開局申請から約一ヶ月で無線局免許証が送られてきます。ここで初めてコールサインが付与されて、アマチュア無線局として無線に応答できるようになります。
Amazonで開局申請に必要なものを買う。
長い道のりですよね。

スタックダンプの読み方

レジスタのEBPを基準にして読み解いていきます。EBPで示されるアドレスの手前4バイトが呼び出し元アドレス、EBP以降が引数です。EBPで示される場所に格納されている4バイトが関数呼び出し前のEBPアドレスです。
EBPが0x00C00018の場合を例としてスタックを読み解きます。

0x00C00010 : 00 00 00 04 // 引数、または、スタック変数
0x00C00014 : 00 00 00 03 // 引数、または、スタック変数
0x00C00018 : 00 C0 00 28 // 手前のEBPアドレス
0x00C0001C : 00 40 10 40 // 呼び出し元アドレス
0x00C00020 : 00 00 00 02 // 引数、または、スタック変数
0x00C00024 : 00 00 00 01 // 引数、または、スタック変数
0x00C00028 : 00 C0 00 40 // 手前のEBPアドレス
0x00C0002C : 00 40 10 80 // 呼び出し元アドレス

cdecl呼び出し規約や、stdcall呼び出し規約では、引数は右に書かれているものから順にスタックに格納されます。したがってアドレスの大きいものから順に、右から左の引数となります。Pascal呼び出し規約では逆に左から順に格納されます。
C++の場合this ポインタがスタックに追加されます。thisポインタはすべての引数をスタックに格納した後、最後にスタックに積まれます。Windowsでは関数が引数を伴わない場合には、thisポインタをスタックに積まずに、ECXレジスタに格納して関数を呼び出す場合があります。
スタック変数の積まれる順序は保障されません。最適化の結果、順不同にスタックに積まれます。

スタックの取得(ネィテブデバッガを作る2)

デバッグを行う上で実行位置に続いて重要なのがスタックの情報です。
別プロセスのスタック情報を取得するには、ReadProcessMemory APIを使用します。「ネィティブデバッガを作る」で取得したCONTEXT構造体のEspレジスタで示されるアドレス以降のデータを読み出します。

BYTE stackPointer[64];
DWORD readedSize(0);
HANDLE hProcess(0);
hProcess = ::OpenProcess(PROCESS_VM_READ, FALSE, debugEvent->dwProcessId);
if (NULL != hProcess)
{
// スタック領域からメモリを読み出す
if (::ReadProcessMemory(hProcess, (LPVOID )context.Esp, &readBuff, sizeof(readBuff), &readedSize))
{
// スタックダンプを表示する
}
}

ReadProcessMemory APIで確保されていないメモリ領域にアクセスすると、デバッグ対象となっているプロセスで不正なメモリアクセスがおこりDebugEventが発生します。ReadProcessMemoryで不正なメモリアクセスを起こし、DebugEventで再びReadProcessMemoryを呼び出し・・・という無限ループに陥らないように注意が必要です。
ReadProcessMemoryの第二パラメータや第三パラメータで割り当てられていないメモリを指定しても、ReadProcessMemoryはエラーを返さずに正常終了します。ReadProcessMemoryがエラーになるか否かで、正しくメモリを読み出せたか判断することはできません。

ネィティブデバッガを作る

WindowsOSやMozillaなどアプリケーションのデバッグ情報を送信する機能を備えたソフトウェアが増えています。Debugging Functions APIを使って実行中の不正なメモリアクセスなどを監視してデバッグ情報を取得する機能を確認してみましょう。
まずデバッグを行うにはCreateProcess APIを使ってデバッガからデバッグ対象のプロセスをDEBUG_PROCESSオプション付きで起動するか、あるいはデバッグ対象のプロセスからデバッガをDEBUG_ONLY_THIS_PROCESSオプション付きで起動する必要があります。
続いてWaitForDebugEvent APIを使用してデバッグ対象プロセス内でイベントが発生するのを待ちます。ここでは不正なメモリアクセスエラーだけを対象として考えます。dwDebugEventCodeがEXCEPTION_DEBUG_EVENT、ExceptionCodeがEXCEPTION_ACCESS_VIOLATIONの場合にエラーをトラップしていみます。これ以外にDLLのLoad/Unload、プロセスやスレッドの開始/停止、デバッグ標準出力へのメッセージや、プロセス内で発生した各種例外を取得することができます。
デバッグ対象プロセスの状態を取得するために、GetThreadContext APIを使用します。これによりデバッグ対象プロセス内で不正なメモリアクセスが発生した時のCPUレジスタの状態を取得できます。取得されるCONTEXT構造体の内容は使用しているCPUのアーキテクチャによって異なります。デバッグにこの情報を利用するためには、各種CPIアーキテクチャ毎にレジスタがどのように扱われるのか熟知している必要があります。
今回はx86 CPUアーキテクチャを対象としますので、CONTEXT構造体のeipレジスタに注目してください。eipレジスタの値が不正なメモリアクセスが発生した時に実行されていたアプリケーションコードの場所をしめします。あとはMAPファイルなどを確認して問題箇所を特定します
デバッグイベントに対する処理が終わったら、ContinueDebugEvent APIを呼び出します。このAPIの呼び出しによりデバッグイベントの発生により一時停止していしるデバッグ対象プロセスの処理を再開させます。

// デバッグ対象のプロセスを開始する
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInfo;
::memset(&processInfo, 0x00, sizeof(processInfo));
::memset(&startupInfo, 0x00, sizeof(startupInfo));
startupInfo.cb		= sizeof(startupInfo);
if (CreateProcess(NULL, m_cmdLineInfo.m_runAppName.GetBuffer(), NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &startupInfo, &processInfo))
{
// デバッグイベントを待つ
DEBUG_EVENT debugEvent;
while (WaitForDebugEvent(&debugEvent, INFINITE))
{
if (EXCEPTION_DEBUG_EVENT == debugEvent.dwDebugEventCode)
{
if (EXCEPTION_ACCESS_VIOLATION == debugEvent.u.Exception.ExceptionRecord.ExceptionCode)
{
// スレッドハンドルの取得
HANDLE hThread(0);
hThread = ::OpenThread(THREAD_GET_CONTEXT, FALSE, debugEvent->dwThreadId);
if (NULL != hThread)
{
// スレッドの状態を取得
CONTEXT		threadContext;
threadContext.ContextFlags	= CONTEXT_ALL;
if (GetThreadContext(hThread, &threadContext))
{
// ここでデバッグ処理をおこなう
}
}
}
}
ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);
}
}

UPS互換バッテリーを購入してみた

我が家はオール電化なのだ。でも一人暮らしだし~と60A契約にしている。これで、冬場に暖房をつけつつ、パソコン立ち上げたまま、TVを見つつ、電子レンジを使いつつ、調理などをすると、ブレーカーを落として白くなることたびたびおこる。
そこでUPSを購入してパソコンにつないでおくことにした。といっても予算はそんなにない。
Yahooオークションなんかでは2000円ぐらいで中古を売っているけど、実は深い訳があるのだ。UPSの正規交換用バッテリーは1万~3万円ぐらいする高価な品物。交換用バッテリーを購入するよさんにちょっと足せば新品を変えてしまうのだ。
でもね・・・実はもっと安い市販のバッテリーでも動くんですよ。
というわけで本体はヤフオクからSmart-UPS 1000を落札。
バッテリーは電圧と容量、サイズ、コネクタの位置などで様々な規格品がありますが、それらがほぼ同じ同等製品であれば同じように使えるはずなのです。というわけで秋月電子からWP12-12を二個購入。
届いたバッテリーをさっそく空けてみますと・・・・微妙にコネクタの形状が異なります。正規品よりちょっとコネクタの横幅がせまいですが、多少狭い分には問題なくつながります。正規品は接着剤で二個のバッテリーが離れないように接合してありますが、そこのところは無視することにします。
で、取り付けて起動!ばっちりですよ♪ただし問題となるのはバッテリの廃棄。私の場合は実家が自動車整備工なんで、自動車用バッテリーに紛らわせて処分してもらうことにします。バッテリーを売っている自動車パーツショップであれば、不要バッテリーの有償引き受けもやっていると思うので、ちゃんと処分しましょう。
ちなみにSmart-UPS 500Jの場合はPXL12050、Smart-UPS 700の場合はWP8-12が使えるらしいです。自己責任でお試しあれ。

Error C2872: ‘IServiceProvider’: あいまいなシンボルです。

C++ CLRで記述したアプリケーションからCOMインターフェースを使用しようとすると「C2872: ‘IServiceProvider’: あいまいなシンボルです。」のコンパイルエラーが表示される。これは.NETのSystem.IServiceProviderとシンボルが重複しているのが原因です。
この問題を回避するには”using namespace System”よりも手前にヘッダファイルの#includeを記述します。

DVDを英国から個人輸入してみた

DVDの個人輸入が2chでちょっと祭りになっていた。英AmazonのDVD売上げのベスト10に日本のアニメが出てしまい、メジャーアニメタイトルの在庫がなくなるほどの盛況ぶりでした。このとき、つい出来心で頼んだDVDがようやく届きはじめたのです。
結論としては思っていたよりはるかに良いです。
さてDVDはリージョンコードや映像形式の違いにより、海外で購入したものを視聴することはできないようになってます。アメリカと日本で劇場公開時期が違っているときなど、劇場公開前にDVDが流通したりするのを防ぐための仕組みです。英国と日本はリージョンコードは同じですがTVの信号形式が異なるため、一般的なDVDプレイヤーやTVでは個人輸入したDVDを見ることはできません。ですがパソコンは英国で使われているPAL信号形式も、日本で使われているNTSC信号形式でも再生することができます。
PAL形式とNTSC形式にはいくつか大きな違いがあります。その一つが解像度です。日本で使われるNTSC形式の水平走査線の数は525本、英国で使われているPAL形式の水平走査線の数は625本、英国のほうが二割ほど解像度が高いのです。HDTVの720pは水平走査線が720本。これには及ばないまでも、パソコンで見てると明らかに画質が違うんですよ。
流石に同じDVDを二枚も持っていないので、動画を比較して提供できないのが残念。

屋外の常夜灯をLEDに変えてみました。

IMG_5230
IMG_5236

個人輸入していたLEDが届きました。常夜灯として屋外についている、12Vのハロゲンランプの代わりです。35W→3Wに消費電力が減りました。消費電力もさることながら、温度が気になっていたんですよ。芝生のところにあるので、そのうち悪条件が重なると燃え移ったりしないかと不安だったのです。

石壁にスポットをあてて、間接照明になってます。3Wで足りるか不安だったんですけど、まぁ大丈夫な様です。

codファイルを使用したデバッグ

リリース後のアプリケーションで例外が発生した場合、codファイルを使用して例外の発生した行を特定することができます。
コンパイル時に生成された、アセンブリ言語のコードと、コンピュータ語のコードを保存することができます。プロジェクトのプロパティを開いて、C/C++の出力ファイルにある「アセンブリの出力」を変更して、「アセンブリコード、コンピュータ語コード、ソースコード」を選択します。これでビルド時に拡張子codのファイルが生成されます。
マップファイルを使用することで、例外オフセットから障害が発生したアドレスを調べられることは「マップファイルを使用したデバッグ」で解説しました。

Address Publics by Value Rva+Base Lib:Object
0000:00000001 ___safe_se_handler_count 00000001
0000:00000000 ___ImageBase 00400000
0001:00000000 _wmain 00401000 f crashTest.obj
0001:00000020 ?funcA@@YAHXZ 00401020 f crashTest.obj
0001:00000050 ?funcB@@YAHH@Z 00401050 f crashTest.obj
0001:00000090 ?funcC@@YAXXZ 00401090 f crashTest.obj

ここで例外の発生している関数funcBと例外オフセットアドレスの差を求めます。この場合、例外オフセットが0x1064、 関数の先頭アドレスが0x1050で、差分は0x14(20)バイトです。ここでcodファイルのfuncBの場所を参照します。

PUBLIC ?funcB@@YAHH@Z ; funcB
; Function compile flags: /Odtp
; COMDAT ?funcB@@YAHH@Z
_TEXT SEGMENT
_val$ = -4 ; size = 4
_arg1$ = 8 ; size = 4
?funcB@@YAHH@Z PROC ; funcB, COMDAT

; 29 : {

00000 55 push ebp
00001 8b ec mov ebp, esp
00003 51 push ecx

; 30 : char *val = NULL;

00004 c7 45 fc 00 00
00 00 mov DWORD PTR _val$[ebp], 0

; 31 : strcpy(val, “Hello World”); // 1.ソースコードの31行目で例外が発生している

0000b 8b 45 fc mov eax, DWORD PTR _val$[ebp]
0000e 8b 0d 00 00 00
00 mov ecx, DWORD PTR $SG-6
00014 89 08 mov DWORD PTR [eax], ecx // 2.ここで例外が発生している
00016 8b 15 04 00 00
00 mov edx, DWORD PTR $SG-6+4
0001c 89 50 04 mov DWORD PTR [eax+4], edx
0001f 8b 0d 08 00 00
00 mov ecx, DWORD PTR $SG-6+8
00025 89 48 08 mov DWORD PTR [eax+8], ecx

; 32 : printf(“call funcB”);

00028 68 00 00 00 00 push OFFSET $SG-7
0002d ff 15 00 00 00
00 call DWORD PTR __imp__printf
00033 83 c4 04 add esp, 4

; 33 : return 0;

00036 33 c0 xor eax, eax

; 34 : }

00038 8b e5 mov esp, ebp
0003a 5d pop ebp
0003b c3 ret 0
?funcB@@YAHH@Z ENDP ; funcB
_TEXT ENDS

0x0014バイトの個所を探すと、2.の個所で例外が発生していることがわかります。これは1.で示されるソースコード上の31行目にあたります。この作業でリリース後のアプリケーションでもソースコード状の何処で例外が発生しているのか特定することができます。