2013-01-09 9 views
5

Sto cercando di imparare come creare file DOS .EXE utilizzando assembly (NASM), costruendo l'intestazione a mano e assemblando il file come binario. Ho un problema con le opzioni della pagina (sia il numero totale di pagine che il numero di byte nella pagina finale). Non importa quanto piccolo imposto i valori iniziali, il programma funzionerà.Importanza del numero di pagine e dell'ultima dimensione di pagina in un header MZ (DOS, 16 bit) .EXE

Come un caso estremo, le seguenti funzioni del programma anche quando si imposta 1 Pagina di 1 byte:

; 
; 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 

Esperimenti con diverse dimensioni del programma, sono giunto alla conclusione che Dos carica tutti i 512 byte di ogni pagina in memoria. In tal caso, qual è lo scopo del numero di byte nell'ultima pagina?

Può interferire con. Bss, stack di dati e/o allocazioni di memoria dinamica?

risposta

3

Il numero totale di pagine non è sicuramente ignorato, viene persino utilizzato dai programmi che non vogliono caricare inizialmente tutti i loro file. Leggeranno i frammenti necessari più tardi loro stessi. Il campo bytes in the last page può o non può essere ignorato, a seconda della versione del sistema operativo. Potrebbe anche essere arrotondato a un paragrafo o al limite del settore del disco. Non dovresti dipendere da un particolare comportamento e riempirlo correttamente.

Il codice di test funziona perché è piccolo e il sistema operativo specifico ha scelto di caricarne una quantità sufficiente in memoria. Se si rende il programma più grande di una singola pagina ma si specifica ancora 1 nel campo page count, probabilmente il codice non sarà completamente caricato e non funzionerà. Ho provato:

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

questo non riesce se page count è 1, ma funziona se page count è 2 (usato dosbox per la prova).

0

Il campo del conteggio delle pagine è utilizzato da DOS, non da Windows NT.

Gli unici due campi di IMAGE_DOS_HEADER utilizzati da NT sono e_magic (che deve essere IMAGE_DOS_SIGNATURE) e e_lfanew che è un offset inferiore 4MB dall'inizio della IMAGE_DOS_HEADER ad una struttura IMAGE_NT_HEADERS che contiene tutte le informazioni per il caricatore NT .

Problemi correlati