中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

中国DOS联盟论坛
现在时间是 2026-08-29 11:36
中国DOS联盟论坛 » DOS开发编程 & 发展交流 (开发室) » DOS下关机的源程序(汇编) 查看 3,700 回复 4
楼 主 DOS下关机的源程序(汇编) 发表于 2003-06-30 00:00 ·  中国 江西 吉安 电信
版主
★★★★
积分 7,296
发帖 1,628
注册 2002-10-16 12:00
23年会员
UID 10
性别 男
状态 离线
.Model tiny
.Code
Org 100h
Start:

mov ax,5300h
xor bx,bx
int 15h ; Check APM install
jnb @@1
jmp ExitSys

@@1:
cmp bx,504Dh ; sign
jz @@2
jmp ExitSys

@@2:
cmp ax,101h ; ver 1.1
jnb @@3
jmp ExitSys

@@3:
push cx
mov Version,ax
mov ax,5400h
xor bx,bx
int 2Fh ; power.exe install check?
xor ax,ax
cmp bx,504Dh
jnz @@4
push ax ; power.exe version
mov ax,5401h
mov bx,100h
int 2Fh ; set management enable
pop ax
jb @@4
inc ax
@@4:
pop cx
push ax
push bx
push cx
mov ax,5301h
xor bx,bx
int 15h ; real-mode interface
mov ax,530Eh
xor bx,bx
mov cx,101h
int 15h ; driver version
mov ax,530Fh
mov bx,1
mov cx,bx
int 15h ; engage power management
mov ax,5308h
mov bx,1
mov cx,bx
int 15h ; enable power mamagement
mov ax,5307h
mov bx,1
mov cx,3
int 15h ; power off
pop cx ; support device

test cl,8 ; BIOS power management disable?
jz @@5
push cx
mov ax,5308h
mov bx,1
xor cx,cx
int 15h ; system stand-by
pop cx

@@5:
test cl,10h ; BIOS power disengaged
jz @@6
mov ax,530Fh
mov bx,1
xor cx,cx
int 15h ; disengage power management

@@6:
mov ax,5304h
xor bx,bx
int 15h ; disconnect interface
pop bx
pop ax
test ax,ax
jz ExitSys
mov ax,5401h
mov bl,bh
mov bh,1
int 2Fh ; set APM firmware power manager enable

ExitSys:

mov ax,4c00h
int 21h

Version DW ?

End Start
[已使用 Gemini 解答]
Gemini 解答

这段汇编代码是一个典型的 16 位 DOS COM 程序,旨在通过调用 APM(Advanced Power Management,高级电源管理)BIOS 中断规范来实现主机软关机(Power Off)。

1. 核心流程与 APM 规范机制

在 ACPI 普及之前(ATX 电源早期及 Windows 95/98 时代),PC 平台的电源管理主要依赖 APM 规范(标准调用入口为 INT 15h, AX=53xxh)。该程序按照标准的 APM 状态机步骤执行:

  1. APM 安装检查与版本确认(INT 15h, AX=5300h
    • 检查系统是否支持 APM,若支持,BIOS 会清除进位标志(CF=0),并在 BX 中返回特征签名 504Dh(ASCII 码的 'PM'),在 AX 中返回 BCD 编码的 APM 版本号。
    • 程序要求版本必须大于或等于 1.1(AX >= 0101h),因为 APM 1.0 不支持关机(Power Off)状态码。
  2. POWER.EXE 状态检测与处理(INT 2Fh, AX=5400h
    • 检测 MS-DOS 自带的 APM 驱动 POWER.EXE 是否已加载,若已加载则先调整其管理状态,避免后续直接调用 BIOS 时产生冲突。
  3. 建立实模式接口连接(INT 15h, AX=5301h
    • 告诉 APM BIOS 当前程序将以实模式(Real Mode)方式进行电源管理调用。
  4. 设置驱动版本(INT 15h, AX=530Eh
    • 将驱动连接版本显式指定为 APM 1.1(CX=0101h)。
  5. 接管与启用电源管理(INT 15h, AX=530Fh / AX=5308h
    • BX=0001h 表示操作对象为“所有设备(All Devices)”。
    • 先通过 530Fh, CX=1 启用对电源状态的控制(Engage),再通过 5308h, CX=1 启用电源管理功能(Enable)。
  6. 执行关机(INT 15h, AX=5307h
    • BX=0001h(所有设备),CX=0003h(状态:Power Off)。
    • 在支持 ATX 软断电的正常硬件上,BIOS 处理该中断后会直接向南桥芯片或电源管理控制器发送断电信号,机器在执行到这条指令时便会立即切断电源
  7. 失败回退与清理逻辑(@@5 之后)
    • 如果关机失败(硬件不支持软关机或 BIOS 拒绝执行),CPU 会继续执行后续指令:依次尝试挂起/恢复状态、断开 APM 连接(INT 15h, AX=5304h),最后返回 DOS。

2. 代码中的设计缺陷与潜在隐患

虽然逻辑框架完整,但代码存在几处细节问题:

  • 磁盘缓存未刷新(最严重隐患): 在 DOS 环境下,如果系统加载了写延迟缓存工具(如 SMARTDRV.EXE),直接调用硬件断电会导致滞留在内存中的脏数据丢失,引发文件系统损坏。标准做法应在关机调用前,通过 DOS 复位驱动器(INT 21h, AH=0Dh)或调用 SmartDrive 的刷新接口(INT 2Fh, AX=4A10h, BX=0001h)强制刷盘。
  • 寄存器堆栈平衡混乱: 在执行 INT 15h, AX=5307h 之前,程序执行了三次 pushax, bx, cx)。在关机调用之后立即执行了 pop cx,但在随后的 @@5 条件分支中,push cxpop cx 位于跳转分支内部,若条件不满足跳过 push cx,会导致后续的栈指针(SP)错位,最终引发崩溃或无法正常返回 DOS。
  • 错误检测缺失: 中间所有的 INT 15h 功能调用均未对返回的进位标志(CF)进行校验。如果其中某一步骤失败(例如接口已被其他程序占用),后续的调用可能全部无效。

3. 运行环境与兼容性边界

  • AT 架构老机器:老式的 AT 电源使用的是物理自锁式机械开关,主板没有软断电电路,调用该程序只能使系统处于挂起/降频状态,无法实现切断电源。
  • ATX 架构(Pentium II 至 Pentium 4 早期):标准支持 APM 1.1/1.2,在纯 DOS 或 Windows 98 纯 DOS 模式下可以完美切断主机电源。
  • 现代 UEFI / ACPI 机器及虚拟机: 现代 PC 的 BIOS 大多已经彻底移除了 APM 实模式接口,全面转用 ACPI;在部分虚拟机(如较新版本的 VMware / VirtualBox 或 DOSBox 默认配置)中,APM 中断可能未被模拟或默认禁用,会导致程序在首个版本检测处直接退出,无法执行关机。
ko20010214
=================================
大功告成,打个Kiss!
ko20010214@MSN.com
神州优雅Q300C
Intel CeleronM 370处理器 | 256MbDDR内存
40G硬盘 | USB2.0 | IEEE 1394
13.3 ' WXGA 宽屏(16:10) | COMBO光驱
10/100M网卡 | 四合一读卡器
2 发表于 2003-06-30 00:00 ·  中国 广西 南宁 联通
初级用户
积分 118
发帖 6
注册 2003-06-04 00:00
23年会员
UID 3365
性别 男
状态 离线
我试试看行不行。:)
3 发表于 2003-07-02 00:00 ·  中国 湖北 黄石 电信
中级用户
★★
积分 349
发帖 78
注册 2003-03-12 00:00
23年会员
UID 1102
性别 男
状态 离线

谢谢你了,我会珍惜的。
4 发表于 2003-07-24 00:00 ·  中国 广东 汕尾 电信
中级用户
★★
积分 417
发帖 137
注册 2003-05-30 00:00
23年会员
UID 2638
性别 男
状态 离线
THANK YOU!
5 发表于 2017-02-02 21:47 ·  中国 广东 深圳 电信
中级用户
★★
积分 271
发帖 74
注册 2004-11-17 00:00
21年会员
UID 33721
性别 男
状态 离线
save,thank you
论坛跳转: