2013-01-09 10 views
5

アセンブリ(NASM)を使用してDos .EXEファイルを作成し、手作業でヘッダーを構築し、ファイルをアセンブルする方法を学習しようとしていますバイナリとして。ページオプション(ページの総数と最終ページのバイト数の両方)に問題があります。初期値をどれくらい小さく設定しても、プログラムは機能します。極端な場合として MZ(DOS、16ビット).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 

、私はドスは、各ページのすべての512のバイトをロードするという結論になってきましたメモリに保存する。もしそうなら、最後のページのバイト数の目的は何ですか?

.bss、スタックデータ、および/またはダイナミックメモリ割り当てを妨害できますか?

答えて

3

合計ページ数は間違いなく無視されますが、最初にすべてのファイルを読み込まないようにするプログラムでも使用されます。彼らは後で必要な断片を読むでしょう。 bytes in the last pageフィールドは、OSのバージョンによっては無視されても無視されなくてもかまいません。また、段落またはディスクセクタの境界に切り上げることもできます。あなたは特定の行動に依存せず、適切に記入するべきです。

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

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 countは(テストのためdosboxを使用)2である場合に動作するかどうかこれが失敗しました。

0

ページカウントフィールドは、Windows NTではなくDOSによって使用されます。 NTで使用IMAGE_DOS_HEADERの

のみ2つのフィールドは(IMAGE_DOS_SIGNATUREでなければならない)e_magicであり、オフセット未満4メガバイトよりIMAGE_DOS_HEADER開始からNTローダーのための情報のすべてを含むIMAGE_NT_HEADERS構造にあるe_lfanew 。

関連する問題