私が気にする100の事象

気にしなければ始まらない。

12021-05-27

昨日の日記(12021年5月27日)です。 天気は曇り。 電波は悪い。

exeファイルを読んでみる 2日目

はい。

続きをしました。

MZスタブ

MZスタブでSignature以外にPEシグネチャのオフセットを見るべきでした。

   Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
 00000000: 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00    MZ..............
!          4D 5A <------------------------------------------- Signature
 00000010: B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00    8.......@.......
 00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
 00000030: 00 00 00 00 00 00 00 00 00 00 00 00 F0 00 00 00    ............p...
!                                              F0 00 00 00 <- PEシグネチャの
!                                                             オフセット
 00000040: 0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68    ..:..4.M!8.LM!Th
 00000050: 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F    is.program.canno
 00000060: 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20    t.be.run.in.DOS.
 00000070: 6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00    mode....$.......
 00000080: 45 DE DD 36 01 BF B3 65 01 BF B3 65 01 BF B3 65    E^]6.?3e.?3e.?3e
 00000090: 08 C7 20 65 0B BF B3 65 BF CE B2 64 02 BF B3 65    .G.e.?3e?N2d.?3e
 000000a0: BF CE B6 64 10 BF B3 65 BF CE B7 64 0B BF B3 65    ?N6d.?3e?N7d.?3e
 000000b0: BF CE B0 64 02 BF B3 65 5A D7 B2 64 03 BF B3 65    ?N0d.?3eZW2d.?3e
 000000c0: 01 BF B2 65 2E BF B3 65 97 CD BB 64 00 BF B3 65    .?2e.?3e.M;d.?3e
 000000d0: 97 CD 4C 65 00 BF B3 65 97 CD B1 64 00 BF B3 65    .MLe.?3e.M1d.?3e
 000000e0: 52 69 63 68 01 BF B3 65 00 00 00 00 00 00 00 00    Rich.?3e........

ドキュメントによると、

At location 0x3c, the stub has the file offset to the PE signature.

と書かれています。

つまり、 PEシグネチャがF0番目にある、 つまりF0番目からCOFFヘッダファイルが始まるということがわかります。

どうやら、 MZスタブには DOSヘッダとDOSスタブがあるみたいです。

DOSヘッダ

今日はちゃんと見ましょう。

   Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
 00000000: 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00    MZ..............
!          4D 5A <------------------------------------------- Signature
!                90 00 <------------------------------------- Bytes on last page
!                                                             of file
!                      03 00 <------------------------------- Pages in file
!                            00 00 <------------------------- Relocations
!                                  04 00 <------------------- Size of header
!                                                             in paragraphs
!                                        00 00 <------------- Minimum extra
!                                                             paragraphs needed
!                                              FF FF <------- Maximum extra
!                                                             paragraphs needed
!                                                    00 00 <- Initial (relative)
!                                                             SS value
 00000010: B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00    8.......@.......
!          B8 00 <------------------------------------------- Initial SP value
!                00 00 <------------------------------------- Checksum
!                      00 00 <------------------------------- Initial IP value
!                            00 00 <------------------------- Initial (relative)
!                                                             CS value
!                                  40 00 <------------------- File address of
!                                                             relocation table
!                                        00 00 <------------- Overlay number
!                                              00 00 00 00
 00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
!          00 00 00 00 <------------------------------------- Reserved words
!                      00 00 <------------------------------- OEM identifier
!                            00 00 <------------------------- OEM information
!                                  00 00 00 00 00 00 00 00
 00000030: 00 00 00 00 00 00 00 00 00 00 00 00 F0 00 00 00    ............p...
!          00 00 00 00 00 00 00 00 00 00 00 00 <------------- Reserved words
!                                              F0 00 00 00 <- File address of
!                                                             new exe header

DOSスタブ

   Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
 00000040: 0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68    ..:..4.M!8.LM!Th
!          0E <---------------------------------------------- push cs
!             1F <------------------------------------------- pop ds
!                BA 0E 00 <---------------------------------- mov dx, 0Eh
!                         B4 09 <---------------------------- mov ah, 09h
!                               CD 21 <---------------------- int 21h
!                                     B8 01 4C <------------- mov ax, 4C01h
!                                              CD 21 <------- int 21h
!                                                    54 68
 00000050: 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F    is.program.canno
!          69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F
 00000060: 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20    t.be.run.in.DOS.
!          74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20
 00000070: 6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00    mode....$.......
!          6D 6F 64 65 2E <---------------------------------- This program cannot
!                                                             be run in DOS mode.
!                         0D <------------------------------- \r
!                            0D <---------------------------- \r
!                               0A <------------------------- \n
!                                  24 <---------------------- $
    push    cs
    pop     ds
    mov     dx, 0Eh
    mov     ah, 09h
    int     21h
    mov     ax, 4C01h
    int     21h

解説を追加します。

    push    cs
    pop     ds
; CSレジスタをプッシュして、DSレジスタにポップしています。
    mov     dx, 0Eh
; 0EhをDXレジスタに転送します。
    mov     ah, 09h
; 09hをAHレジスタに転送します。
    int     21h
; int はInterrupt(割り込み)という意味です。
; 8086には「割り込みベクタ」という概念があり、割り込み処理の管理がしやすいようになっています。
; 8086は int 00h から int FFh まで、合計で256種類の割り込みの利用ができます。
; そして、MS-DOSでは、 int 21h で主なDOS APIを呼び出すことができます。
; 具体的に提供される機能はAHレジスタに入っている値によって変わります。
; AHレジスタに09hが入っている場合は、DXレジスタが指すアドレスにある文字列を表示します。
; つまり、
; mov dx, 0Eh
; mov ah, 09h
; int 21h
; の3行で「0Ehにある文字列(つまり'This program cannot be run in DOS mode.\r\r\n')を標準出力する」という意味になります。
; ちなみに、0Ehというのは相対位置なので、コードが始まるアドレス00000040+DXレジスタが指すアドレス0Ehで絶対位置だと0000004Eとなります。
; 文字列は24h($)のところで終わります。
    mov     ax, 4C01h
; 4ChをAHレジスタに、01をALレジスタに転送します。
    int     21h
; また int 21h ですね。
; AHレジスタに4Chが入っている場合は、ALレジスタに入っている値を戻り値として終了します。
; つまり、
; mov ax, 4C01h
; int 21h
; の2行で「1を返してプログラムを終了する」という意味になります。

「文字列は24h($)のところで終わります。」 これを見て、「あれ?ヌル文字じゃないの?」と思った方がいるかもしれません。 というか私はそうでした。 しかし、調べてみるとWikipediaString の記事には次のことが書かれています。

Using a special byte other than null for terminating strings has historically appeared in both hardware and software, though sometimes with a value that was also a printing character. $ was used by many assembler systems, : used by CDC systems (this character had a value of zero), and the ZX80 used "[3] since this was the string delimiter in its BASIC language.

文字列を終了するためにnull以外の特別なバイトを使用することがあって、例えば$は多くのアセンブラで使用されてたらしいですね。

ゴミ

00000080~000000e0は多分ゴミです。 余り?ですね。 ここに何書いても動きそうではあります。

 00000080: 45 DE DD 36 01 BF B3 65 01 BF B3 65 01 BF B3 65    E^]6.?3e.?3e.?3e
 00000090: 08 C7 20 65 0B BF B3 65 BF CE B2 64 02 BF B3 65    .G.e.?3e?N2d.?3e
 000000a0: BF CE B6 64 10 BF B3 65 BF CE B7 64 0B BF B3 65    ?N6d.?3e?N7d.?3e
 000000b0: BF CE B0 64 02 BF B3 65 5A D7 B2 64 03 BF B3 65    ?N0d.?3eZW2d.?3e
 000000c0: 01 BF B2 65 2E BF B3 65 97 CD BB 64 00 BF B3 65    .?2e.?3e.M;d.?3e
 000000d0: 97 CD 4C 65 00 BF B3 65 97 CD B1 64 00 BF B3 65    .MLe.?3e.M1d.?3e
 000000e0: 52 69 63 68 01 BF B3 65 00 00 00 00 00 00 00 00    Rich.?3e........

いや、分かりません。 これについて詳しく書いてある資料があったら教えて下さい。

今日はこれで終わり。