汇编中伪指令org作用详解
摘要:记录一下汇编中伪指令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 动态调试时的截图:
注意此时的 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 动态调试时的截图:
注意此时的 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 动态调试时的截图:
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 0100h 后,观察此时 0B29:0102 处的 代码,可以发现 DX 寄存器处的值为 0x010C。这个地方加上 CS的寄存器的值 0x0B29,刚好是字符串"Hello, a .COM file is running!$"在内存器中存放的地址。这个时候程序运行正常。
代码资源
参考链接
汇编 .COM 文件
com文件简介
DOS下COM文件的加载过程
为什么dos下的com文件都要org 0100h呢?为什么系统启动时要org 07c00h呢
操作系统学习常见疑惑问与答[编码实践部分]—问题1:org指令深入理解
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。