2013-01-09 13 views
5

मैं सीखने की कोशिश कर रहा हूं कि असेंबली (NASM) का उपयोग करके डॉस .EXE फ़ाइलों को कैसे बनाया जाए, हाथ से हेडर का निर्माण और फ़ाइल को इकट्ठा करना बाइनरी के रूप में मुझे पृष्ठ विकल्पों में समस्या है (पृष्ठों की कुल संख्या और अंतिम पृष्ठ पर बाइट गिनती)। कोई फर्क नहीं पड़ता कि मैं शुरुआती मूल्य कितना छोटा सेट करता हूं, कार्यक्रम काम करेगा।पृष्ठ गणना और एमजेड (डॉस, 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 फ़ील्ड को अनदेखा किया जा सकता है या नहीं भी किया जा सकता है। इसे अनुच्छेद या डिस्क सेक्टर सीमा तक भी गोल किया जा सकता है। आपको किसी विशेष व्यवहार पर निर्भर नहीं होना चाहिए और इसे ठीक से भरना चाहिए।

आपका टेस्ट कोड काम करता है क्योंकि यह छोटा है और आपके विशेष ओएस ने इसे पर्याप्त रूप से स्मृति में लोड करना चुना है। यदि आप अपने प्रोग्राम को एक पृष्ठ से बड़ा बनाते हैं लेकिन 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 2 है काम करता है (परीक्षण के लिए dosbox प्रयुक्त)।

0

पेज गिनती फ़ील्ड का उपयोग डॉस द्वारा किया जाता है, न कि विंडोज एनटी द्वारा। NT द्वारा प्रयोग किया जाता IMAGE_DOS_HEADER की

केवल दो क्षेत्रों e_magic हैं (जो IMAGE_DOS_SIGNATURE होना चाहिए) और e_lfanew जो एक ऑफसेट एक IMAGE_NT_HEADERS संरचना है कि NT लोडर के लिए जानकारी होती है करने के लिए IMAGE_DOS_HEADER की शुरुआत से 4MB से भी कम है ।

संबंधित मुद्दे