use*_*876 10
您需要说明它是什么处理器系列以及您正在使用的操作系统.还有你的代码运行的特权 - 如果它是内核代码,那么它拥有比用户代码更多的特权.
假设您在Intel x86系列CPU上使用Windows NT系列的某些成员(包括XP或Vista),并且您的代码是正常(用户空间)代码,那么......您需要调用Windows内置函数做这个.你不能只执行一些神奇的装配序列.
即使您可以执行一些神奇的汇编序列,您也不会想要 - 您几乎肯定希望让操作系统有机会将数据从磁盘缓存写入磁盘,并执行其他优雅关闭的操作.
如果您正在为x86编写自己的操作系统,那么您需要查看ACPI(或APM)规范.如果GPL代码没问题,那么相关的Linux内核例程就在这里(ACPI)和这里(APM).
这是我用来在DOS模式下关闭电脑多年的29字节程序.
;Connect to APM API
MOV AX,5301
XOR BX,BX
INT 15
;Try to set APM version (to 1.2)
MOV AX,530E
XOR BX,BX
MOV CX,0102
INT 15
;Turn off the system
MOV AX,5307
MOV BX,0001
MOV CX,0003
INT 15
;Exit (for good measure and in case of failure)
RET
Run Code Online (Sandbox Code Playgroud)
您可以在DJGPP使用Ralf Brown的中断列表查找更多功能.
小智 7
在Linux中读取reboot(2).
来源文件:
kernel/sys.c kernel/exit.c和arch/x86/kernel/apm.c
不是一个完整的答案,但我认为这是一个良好的开端.我将不得不阅读我的BIOS机器代码,看看他们做了什么.但这部分是机器特定的.如果您知道主板上的IC控制电源,您可以找出所需的IO端口,寄存器和命令.然后设置正确的板/设备状态,然后发出命令关闭电源.
BIOS通过INT 15h ah = 53h管理电源(所谓的高级电源管理又称APM)函数al = 07在Linux中使用的是设置电源状态cmd.参数bx = 0001h表示所有设备,cx = 0003k表示停止.
小智 5
来自 arch/x86/kernel/amp.c:
/**
* apm_power_off - ask the BIOS to power off
*
* Handle the power off sequence. This is the one piece of code we
* will execute even on SMP machines. In order to deal with BIOS
* bugs we support real mode APM BIOS power off calls. We also make
* the SMP call on CPU0 as some systems will only honour this call
* on their first cpu.
*/
static void apm_power_off(void)
{
unsigned char po_bios_call[] = {
0xb8, 0x00, 0x10, /* movw $0x1000,ax */
0x8e, 0xd0, /* movw ax,ss */
0xbc, 0x00, 0xf0, /* movw $0xf000,sp */
0xb8, 0x07, 0x53, /* movw $0x5307,ax */
0xbb, 0x01, 0x00, /* movw $0x0001,bx */
0xb9, 0x03, 0x00, /* movw $0x0003,cx */
0xcd, 0x15 /* int $0x15 */
};
/* Some bioses don't like being called from CPU != 0 */
if (apm_info.realmode_power_off) {
set_cpus_allowed_ptr(current, cpumask_of(0));
machine_real_restart(po_bios_call, sizeof(po_bios_call));
} else {
(void)set_system_power_state(APM_STATE_OFF);
}
}
Run Code Online (Sandbox Code Playgroud)
代码现在在apm_32.c 中。搜索“apm_power_off”。
将上面的@larz 答案转换为 nasm 程序集的操作如下:
先决条件:Bochs、Nasm
这个例子是在带有标准包的 debian wheezy 上运行的。
代码(文件名:shutdown.asm):
org 0x7c00
jmp main
Shutdown:
mov ax, 0x1000
mov ax, ss
mov sp, 0xf000
mov ax, 0x5307
mov bx, 0x0001
mov cx, 0x0003
int 0x15
WaitForEnter:
mov ah, 0
int 0x16
cmp al, 0x0D
jne WaitForEnter
ret
main:
call WaitForEnter
call Shutdown
times 510-($-$$) db 0
dw 0xaa55
Run Code Online (Sandbox Code Playgroud)
Nasm 汇编:
nasm -f bin -o boot_sect.img shutdown.asm
Run Code Online (Sandbox Code Playgroud)
Bochs 配置文件(文件名:.bochsrc)与代码(shutdown.asm)在同一目录
display_library: sdl
floppya: 1_44=boot_sect.img, status=inserted
boot: a
Run Code Online (Sandbox Code Playgroud)
*注意我正在使用 bochs 的 sdl 库,它是与 bochs 本身分开的一个包
运行 bochs(来自与之前相同的目录):
bochs
Run Code Online (Sandbox Code Playgroud)
按回车关机
*注意我不确定 Shutdown 标签和 WaitForEnter 标签之间的所有行都是必需的