2013-01-09 20 views
5

Próbuję się nauczyć, jak tworzyć pliki .EXE za pomocą zestawu (NASM), konstruować nagłówek ręcznie i składać plik jako binarny. Mam problem z opcjami strony (zarówno całkowita liczba stron, jak i liczba bajtów na ostatniej stronie). Bez względu na to, jak małe ustawiam wartości początkowe, program będzie działał.Znaczenie licznika stron i rozmiaru ostatniej strony w nagłówku MZ (DOS, 16 bitów) .EXE

W skrajnym przypadku, następujące funkcje programowe nawet przy ustawianiu 1 strona 1 bajt:

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

Eksperymentowanie z różnymi rozmiarami programowych, doszedłem do wniosku, że Dos ładuje wszystkie 512 bajtów każdej strony do pamięci. Jeśli tak, jaki jest cel liczby bajtów na ostatniej stronie?

Czy może kolidować z .bss, danymi stosu i/lub dynamicznymi alokacjami pamięci?

Odpowiedz

3

Łączna liczba stron nie jest zignorowana, jest nawet używana przez programy, które nie chcą, aby cały ich plik był załadowany początkowo. Odczytują potrzebne fragmenty później samodzielnie. Pole bytes in the last page może, ale nie musi być ignorowane, w zależności od wersji systemu operacyjnego. Można go również zaokrąglić w górę do granicy akapitu lub sektora dysku. Nie powinieneś polegać na określonym zachowaniu i prawidłowo go wypełnić.

Twój kod testowy działa, ponieważ jest mały, a Twój system operacyjny wybrał załadowanie go do pamięci. Jeśli zwiększysz program o więcej niż jedną stronę, ale nadal podasz 1 w polu page count, prawdopodobnie Twój kod nie zostanie w pełni załadowany i nie będzie działał. Próbowałem:

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

ta zawodzi jeśli page count jest 1, ale działa, jeśli page count jest 2 (używany dosbox do testowania).

0

Pole liczby stron jest używane przez system DOS, a nie przez system Windows NT.

Tylko dwa pola IMAGE_DOS_HEADER wykorzystywane przez NT są e_magic (który musi być IMAGE_DOS_SIGNATURE) i e_lfanew czyli offset mniej niż 4MB od początku IMAGE_DOS_HEADER do struktury IMAGE_NT_HEADERS, który zawiera wszystkie informacje o ładowarce NT .

Powiązane problemy