我试图学习如何使用程序集(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,堆栈数据和/或动态内存分配吗?
绝对不会忽略总页数,甚至不希望最初加载所有文件的程序使用它.他们将在以后阅读必要的片段.最后一页字段中的字节可能会也可能不会被忽略,具体取决于操作系统版本.它也可以向上舍入到段落或磁盘扇区边界.您不应该依赖于特定的行为并正确地填写它.
原文链接:https://www.f2er.com/windows/441234.html您的测试代码有效,因为它很小,您的特定操作系统已选择将足够的内容加载到内存中.如果您使程序大于单个页面但仍然在页面计数字段中指定1,则可能您的代码将无法完全加载且无法工作.我试过了:
times (32-$+$$) db 0 times (512) nop mov dx,09h ; write string ds:dx to stdout int 21h int 20h
如果页数为1,则会失败,但如果页数为2(使用dosBox进行测试),则会起作用.