摘要:记录一下汇编中伪指令org的作用。

测试环境

(1) windows xp professional 版本 2002 Service Pack 3
(2) masm5.0

相关命令

# 编译org1.asm到org1.obj
c:\masm500>masm org1.asm

# 链接org1.obj到org1.exe
c:\masm500>link org1.obj

# 将org1.exe转换成org1.com
c:\masm500>exe2bin org1.exe org1.com

测试代码

; HELLO.ASM
.model TINY
.code
ORG 0100h      ; <<< 关键指令
start:
    ; DOS 功能调用:显示字符串
    mov ah, 9
    mov dx, offset msg  ; 将 msg 字符串的地址放入 DX
    int 21h             ; 调用 DOS 中断

    ; DOS 功能调用:退出程序
    mov ax, 4C00h       ; 4Ch 是退出功能, 00h 是返回码
    int 21h

; --- 数据区 ---
msg db 'Hello, a .COM file is running!$'  ; '$' 是字符串结束符

END start           ; 指定程序入口点

测试步骤

不加org指令

; HELLO.ASM
.model TINY
.code
start:
    ; DOS 功能调用:显示字符串
    mov ah, 9
    mov dx, offset msg  ; 将 msg 字符串的地址放入 DX
    int 21h             ; 调用 DOS 中断

    ; DOS 功能调用:退出程序
    mov ax, 4C00h       ; 4Ch 是退出功能, 00h 是返回码
    int 21h

; --- 数据区 ---
msg db 'Hello, a .COM file is running!$'  ; '$' 是字符串结束符

END start           ; 指定程序入口点
# 编译org1.asm到org1.obj
c:\masm500>masm org1.asm

# 链接org1.obj到org1.exe
c:\masm500>link org1.obj

# 将org1.exe转换成org1.com
c:\masm500>exe2bin org1.exe org1.com

org1.exe通过IDA反汇编后的代码:

seg000:0000                 public start
seg000:0000 start           proc near
seg000:0000                 mov     ah, 9
seg000:0002                 mov     dx, 0Ch
seg000:0005                 int     21h             ; DOS - PRINT STRING
seg000:0005                                         ; DS:DX -> string terminated by "$"
seg000:0007                 mov     ax, 4C00h
seg000:000A                 int     21h             ; DOS - 2+ - QUIT WITH EXIT CODE (EXIT)
seg000:000A start           endp                    ; AL = exit code
seg000:000A
seg000:000A ; ---------------------------------------------------------------------------
seg000:000C                 db 48h, 65h, 2 dup(6Ch), 6Fh, 2Ch, 20h, 61h, 20h, 2Eh
seg000:000C                 db 43h, 4Fh, 4Dh, 20h, 66h, 69h, 6Ch, 65h, 20h, 69h, 73h
seg000:000C                 db 20h, 72h, 75h, 2 dup(6Eh), 69h, 6Eh, 67h, 21h, 24h
seg000:000C seg000          ends
seg000:000C
seg000:000C
seg000:000C                 end start

org1.exe 动态调试时的截图:

汇编中伪指令org作用详解1.png

注意此时的 0B39:0002 代码,可以发现 DX 寄存器处的值为 0x000C。这个地方加上 CS的寄存器的值 0x0B39,刚好是字符串"Hello, a .COM file is running!$"在内存器中存放的地址。这个时候程序运行正常。

org1.com通过IDA反汇编后的代码:

seg000:0100
seg000:0100 ; =============== S U B R O U T I N E =======================================
seg000:0100
seg000:0100 ; Attributes: noreturn
seg000:0100
seg000:0100                 public start
seg000:0100 start           proc near
seg000:0100                 mov     ah, 9
seg000:0102                 mov     dx, 0Ch
seg000:0105                 int     21h             ; DOS - PRINT STRING
seg000:0105                                         ; DS:DX -> string terminated by "$"
seg000:0107                 mov     ax, 4C00h
seg000:010A                 int     21h             ; DOS - 2+ - QUIT WITH EXIT CODE (EXIT)
seg000:010A start           endp                    ; AL = exit code
seg000:010A
seg000:010A ; ---------------------------------------------------------------------------
seg000:010C                 db 48h, 65h, 2 dup(6Ch), 6Fh, 2Ch, 20h, 61h, 20h, 2Eh
seg000:010C                 db 43h, 4Fh, 4Dh, 20h, 66h, 69h, 6Ch, 65h, 20h, 69h, 73h
seg000:010C                 db 20h, 72h, 75h, 2 dup(6Eh), 69h, 6Eh, 67h, 21h, 24h
seg000:010C seg000          ends
seg000:010C
seg000:010C
seg000:010C                 end start

org1.com 动态调试时的截图:

汇编中伪指令org作用详解2.png

注意此时的 0B29:0102 代码,可以发现 DX 寄存器处的值为 0x000C。这个地方加上 CS的寄存器的值 0x0B29,明显不是字符串"Hello, a .COM file is running!$"在内存器中存放的地址。这个时候程序运行异常。

原因也很简单:.com 程序载入内存后,操作系统会在代码段前面插入一个PSP部分(占用0x100H 字节),相当于代码段的所有内容被整体往后挪移了0x100H 字节。

添加org指令

; HELLO.ASM
.model TINY
.code
ORG 0100h      ; <<< 关键指令
start:
    ; DOS 功能调用:显示字符串
    mov ah, 9
    mov dx, offset msg  ; 将 msg 字符串的地址放入 DX
    int 21h             ; 调用 DOS 中断

    ; DOS 功能调用:退出程序
    mov ax, 4C00h       ; 4Ch 是退出功能, 00h 是返回码
    int 21h

; --- 数据区 ---
msg db 'Hello, a .COM file is running!$'  ; '$' 是字符串结束符

END start           ; 指定程序入口点
# 编译org2.asm到org2.obj
c:\masm500>masm org2.asm

# 链接org2.obj到org2.exe
c:\masm500>link org2.obj

# 将org2.exe转换成org2.com
c:\masm500>exe2bin org2.exe org2.com

org2.exe通过IDA反汇编后的代码:

seg000:0100                 public start
seg000:0100 start           proc near
seg000:0100                 mov     ah, 9
seg000:0102                 mov     dx, 10Ch
seg000:0105                 int     21h             ; DOS - PRINT STRING
seg000:0105                                         ; DS:DX -> string terminated by "$"
seg000:0107                 mov     ax, 4C00h
seg000:010A                 int     21h             ; DOS - 2+ - QUIT WITH EXIT CODE (EXIT)
seg000:010A start           endp                    ; AL = exit code
seg000:010A
seg000:010A ; ---------------------------------------------------------------------------
seg000:010C                 db 48h, 65h, 2 dup(6Ch), 6Fh, 2Ch, 20h, 61h, 20h, 2Eh
seg000:010C                 db 43h, 4Fh, 4Dh, 20h, 66h, 69h, 6Ch, 65h, 20h, 69h, 73h
seg000:010C                 db 20h, 72h, 75h, 2 dup(6Eh), 69h, 6Eh, 67h, 21h, 24h
seg000:010C seg000          ends
seg000:010C
seg000:010C
seg000:010C                 end start

org2.exe 动态调试时的截图:

汇编中伪指令org作用详解3.png

org2.com通过IDA反汇编后的代码:

seg000:0100 ; =============== S U B R O U T I N E =======================================
seg000:0100
seg000:0100 ; Attributes: noreturn
seg000:0100
seg000:0100                 public start
seg000:0100 start           proc near
seg000:0100                 mov     ah, 9
seg000:0102                 mov     dx, 10Ch
seg000:0105                 int     21h             ; DOS - PRINT STRING
seg000:0105                                         ; DS:DX -> string terminated by "$"
seg000:0107                 mov     ax, 4C00h
seg000:010A                 int     21h             ; DOS - 2+ - QUIT WITH EXIT CODE (EXIT)
seg000:010A start           endp                    ; AL = exit code
seg000:010A
seg000:010A ; ---------------------------------------------------------------------------
seg000:010C                 db 48h, 65h, 2 dup(6Ch), 6Fh, 2Ch, 20h, 61h, 20h, 2Eh
seg000:010C                 db 43h, 4Fh, 4Dh, 20h, 66h, 69h, 6Ch, 65h, 20h, 69h, 73h
seg000:010C                 db 20h, 72h, 75h, 2 dup(6Eh), 69h, 6Eh, 67h, 21h, 24h
seg000:010C seg000          ends
seg000:010C
seg000:010C
seg000:010C                 end start

org2.com 动态调试时的截图:

汇编中伪指令org作用详解4.png

加上 ORG 0100h 后,观察此时 0B29:0102 处的 代码,可以发现 DX 寄存器处的值为 0x010C。这个地方加上 CS的寄存器的值 0x0B29,刚好是字符串"Hello, a .COM file is running!$"在内存器中存放的地址。这个时候程序运行正常。

代码资源

测试代码.rar

参考链接

汇编 .COM 文件
com文件简介
DOS下COM文件的加载过程
为什么dos下的com文件都要org 0100h呢?为什么系统启动时要org 07c00h呢
操作系统学习常见疑惑问与答[编码实践部分]—问题1:org指令深入理解

文章目录