加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

程序集 – MZ(DOS,16位).EXE标头中页面计数和最后一页大小的重要

发布时间:2020-12-13 21:19:56 所属栏目:Windows 来源:网络整理
导读:我试图学习如何使用程序集(NASM)创建Dos .EXE文件,手动构建标头并将文件组装为二进制文件.我的页面选项有问题(页面总数和最后一页的字节数).无论我设置初始值多小,该程序都可以工作. 作为极端情况,即使设置1个1字节的页面,以下程序也会起作用: ;; the small
我试图学习如何使用程序集(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,堆栈数据和/或动态内存分配吗?

绝对不会忽略总页数,甚至不希望最初加载所有文件的程序使用它.他们将在以后阅读必要的片段.最后一页字段中的字节可能会也可能不会被忽略,具体取决于操作系统版本.它也可以向上舍入到段落或磁盘扇区边界.您不应该依赖于特定的行为并正确地填写它.

您的测试代码有效,因为它很小,您的特定操作系统已选择将足够的内容加载到内存中.如果您使程序大于单个页面但仍然在页面计数字段中指定1,则可能您的代码将无法完全加载且无法工作.我试过了:

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

如果页数为1,则会失败,但如果页数为2(使用dosbox进行测试),则会起作用.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读