汇编语言 EXE 文件与 COM 文件

一、程序段前缀 PSP

程序在执行前调入内存时,由 DOS 确定装入的起始地址,并在此处首先建立一个程序段前缀 PSP(Program Segment Prefix),接着装入程序。PSP 长度为 256 个字节,其中包含很多信息,特别是地址为 [PSP:0] 存放的是 INT 20H(机器码为 CD20),INT 20H 指令为程序返回的中断调用指令,我们对此处信息予以关注,以便理解用 RET 指令可结束程序。

EXE文件装入内存后,有关寄存器的值如下:

DS=ES=PSP 段地址

CS:IP=程序执行的起始地址

SS:SP=堆栈段的栈底地址

我们已经注意到,同一个程序在不同的机器内存中的物理位置是不同的,因为程序不得随意闯入内存,须由 DOS 安排。

程序在装入前无法确定在内存中的物理位置,LINK 后的 DATA 段地址只是一个相对地址,在程序装入内存时,DOS 根据装入的起始地址,把 DATA 段的相对地址转为绝对地址,这就是为何要在程序中对段寄存器(CS 除外)赋值的原因。

EXE 文件允许多个段,可以指定任一条指令为执行的开始地址。EXE 文件除了程序本身,还有文件头。文件头由 LINK 程序生成,其中包括程序的重定位信息,供 DOS 装入文件时用。

地址 PSP:80H~PSP:0FFH 处存放命令行参数,参数直接提供给可执行程序。如执行程序 PROG.EXE,可在 DOS 提示符下键入:

1
PROG par1,par2

这里 par1 和 par2 为参数,则命令行参数域为:0bh,“par1,par2”,0dh。这里 0bh 表示参数长度,0dh 表示回车符。

如果把程序写成过程,可以用 RET 指令结束程序。

例 17 用 RET 指令结束程序。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
data segment      ; 定义数据段data

string  db 'hello,world!$'

data ends

code segment

assume cs:code,ds:data

main proc far

push ds         ; ds进栈

mov ax,0        ; 0进栈

push ax

mov ax,data

mov ds,ax

mov dx,offset string

mov ah,9

int 21h

ret            ; 返回

main endp

code ends

end main

请注意,程序开始就向堆栈压入 DS(PSP 的值)和 0,而在最后,用 ret 指令结束程序。而此时 ret 指令的作用就是把0弹出到寄存器 IP,把 PSP 弹出到寄存器 CS,于是程序就执行 [CS:IP] 也就是 [PSP:0] 处的指令,这个指令就是 INT 20H。

特别需要说明的是,上面的用法是固定的,程序要写成过程形式,否则无效。不要忘记,ret 指令总是写在过程中的,用于返回到调用程序,而此处主过程的 ret 指令是返回到 DOS 系统。程序中也不能用 INT 20H 指令代替此处的 ret 指令。否则虽退出程序但却引起死机。

例 17 程序的调试如图 9 所示。

用 RET 指令结束程序

图 9 用 RET 指令结束程序

二、COM 文件

  1. COM 文件的格式

    还有一种可执行文件,其扩展名为 COM,COM 文件由本身的二进制代码组成,它没有 EXE 文件那样具有文件信息的标题区,在装入内存后,其内容不变,它占用的空间比 EXE 文件要小得多。COM 文件要求源程序只含一个代码段,即 CS=DS=ES=SS,所以占用空间不超过 64KB,程序中如有过程调用,类型应为 NEAR。COM 文件要求程序从 100H 开始执行(前面 256 字节为程序段前缀 PSP 预留空间)。

    COM 文件的源程序格式举例如下:

    例 18 COM 文件的源程序(非过程形式)。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    
    ; hello1.asm
    
    code segment
    
    assume cs:code
    
    org  100h
    
    start:
    
    mov ax,cs
    
    mov ds,ax
    
    mov dx,offset string
    
    mov ah,9
    
    int 21h
    
    mov ah,4ch     ; 退出程序
    
    int 21h
    
    string  db 'hello,world!$'
    
    code  ends
    
    end  start
    

    例 19 COM 文件的源程序(过程形式)。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    
    ; hello2.asm
    
    code  segment
    
    assume  cs:code
    
    org 100h
    
    main  proc  far
    
    push ds
    
    xor ax,ax
    
    push ax
    
    mov ax,cs
    
    mov ds,ax
    
    mov dx,offset string
    
    mov ah,9
    
    int 21h
    
    ret        ; 退出程序
    
    main  endp
    
    string db 'hello,world!$'
    
    code  ends
    
    end main
    
  2. COM 文件的生成

    并不是具有 COM 文件的源程序格式,就一定是 COM 文件,COM 文件也是通过 LINK 连接程序产生,连接命令后面须加上 /T。如:

    1
    
    C:\MASM6\LINK HELLO/T
    

如果同一目录中有两个文件,如 PROG.EXE 和 PROG.COM,当键入 PROG 执行程序时,COM 文件将被执行,键入 PROG.EXE 才能执行 PROG.EXE。

请参阅

(完)

comments powered by Disqus