6

アセンブリ (NASM) を使用して Dos .EXE ファイルを作成し、手動でヘッダーを作成し、ファイルをバイナリとしてアセンブルする方法を学習しようとしています。ページ オプション (総ページ数と最終ページのバイト カウントの両方) に問題があります。初期値をどれだけ小さく設定しても、プログラムは機能します。

極端な例として、以下のプログラムは 1 ページ 1 バイトを設定しても機能します。

;
; the smallest possible "Hello, World!" .EXE (DOS MZ) file
; assemble with:
; nasm -f bin -w+all -O0 smallest_hello_exe.asm -o ASM.EXE
;

bits 16
cpu 8086

;
; by setting cs:ip=-10h:100h instead of 0h:0h inside the .EXE header
; (identical assignments), we achieve the following two advantages:
; 1) ds==cs, so no "push cs pop ds" is needed in order for ds:dx
; to point to the message string
; 2) we can exit by int 20h instead of int 21h, thus omitting the
; ah=4ch assignment
; (int 20h requires that cs points to the PSP segment)
;

;
; we do not the address calculations to take the .EXE header into account
; so we must subtract its length (20h) by an "org -20h"
; but, since ip will be 100h, we must also issue an "org 100h"
; and, since 0x100-0x20=0xE0...

org 0xE0        ; 100h for ip value - 20h for header



section .text align=1
;
; the MZ .EXE header structure
; 28 bytes long
; 1 pararaph equals 16 bytes
; 1 page equals 512 bytes
; suggested reading: int 21h,ah=4bh procedure
;
host_exe_header:
.signature: dw 'MZ'     ; the 'MZ' characters
.last_page_size: dw 1   ; number of used bytes in the final file page, 0 for all
.page_count: dw 1       ; number of file pages including any last partial page
.reloc: dw 0            ; number of relocation entries after the header
.paragraphs: dw 2       ; size of header + relocation table, in paragraphs
.minalloc: dw 0         ; minimum required additional memory, in paragraphs
.maxalloc: dw 0xFFFF    ; maximum memory to be allocated, in paragraphs
.in_ss: dw 0            ; initial relative value of the stack segment
.in_sp: dw 0xF000       ; initial sp value
.checksum: dw 0         ; checksum: 1's complement of sum of all words
.in_ip: dw 100h         ; initial ip value
.in_cs: dw -10h         ; initial relative value of the text segment
.offset: dw 0           ; offset of the relocation table from start of header
.overlay: dw 0          ; overlay value (0h = main program)

; pad header (its size in bytes must be a multiple of 16)
times (32-$+$$) db 0

mov dx,message
mov ah,09h              ; write string ds:dx to stdout
int 21h
int 20h

section .data align=1
message: db 'Hello, World!$'

section .bss align=1

さまざまなプログラム サイズを試してみた結果、Dos は各ページの 512 バイトすべてをメモリにロードするという結論に達しました。もしそうなら、最後のページのバイト数の目的は何ですか?

.bss、スタック データ、および/または動的メモリ割り当てに干渉できますか?

4

2 に答える 2

4

総ページ数は絶対に無視されません。すべてのファイルを最初にロードしたくないプログラムでも使用されます。彼らは後で必要なフラグメントを自分で読み取ります。OSのbytes in the last pageバージョンによって、フィールドが無視される場合とされない場合があります。また、段落またはディスク セクタの境界に切り上げることができます。特定の動作に依存するのではなく、適切に記入してください。

テスト コードは小さく、特定の OS がメモリに十分な量をロードすることを選択したため、機能します。プログラムを 1 ページよりも大きくしてもフィールドで指定する1page count、おそらくコードが完全に読み込まれず、機能しません。私は試した:

times (32-$+$$) db 0
times (512) nop
mov dx,message
mov ah,09h              ; write string ds:dx to stdout
int 21h
int 20h

これpage countは 1 の場合は失敗しますが、 page count2 の場合は機能dosboxします (テストに使用)。

于 2013-01-10T18:08:53.573 に答える
1

ページ数フィールドは、Windows NTではなく、DOSで使用されます。

NTで使用されるIMAGE_DOS_HEADERの2つのフィールドは、e_magic(IMAGE_DOS_SIGNATUREである必要があります)とe_lfanewです。これは、IMAGE_DOS_HEADERの先頭からNTローダーのすべての情報を含むIMAGE_NT_HEADERS構造体までのオフセットが4MB未満です。

于 2013-01-28T07:22:02.807 に答える