Как отключить компьютер, используя только код сборки?
Выключение компьютера с помощью сборки
Ответ 1
Вам нужно сказать, какое это семейство процессоров и какую ОС вы используете. Кроме того, с какими привилегиями работает ваш код - если это код ядра, то он имеет больше привилегий, чем пользовательский код.
Предполагая, что вы используете какой-то член семейства Windows NT (включая XP или Vista) на процессоре семейства Intel x86, и ваш код - это обычный (пользовательский) код, тогда... вам нужно вызвать встроенную функцию Windows, чтобы сделай это. Вы не можете просто выполнить магическую последовательность сборки.
Даже если бы вы могли просто выполнить некоторую магическую последовательность сборки, вы бы этого не хотели - вы почти наверняка хотите дать ОС возможность записывать данные из дискового кэша на диск и выполнять другие операции постепенного отключения.
Если вы пишете свою собственную ОС для x86, то вам нужно взглянуть на спецификации ACPI (или APM). Если с кодом GPL все в порядке, соответствующие подпрограммы ядра Linux находятся здесь (ACPI) и здесь (APM).
Ответ 2
Это 29-байтная программа, которую я использовал, чтобы отключить компьютер в режиме DOS в течение многих лет.
;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
Вы можете искать больше функций с Список прерываний Ralf Browns at DJGPP.
Ответ 3
Взгляните на shutdown.asm от rdos и this тема форума
Ответ 4
В Linux прочитайте перезагрузку (2).
источники, представляющие интерес:
kernel/sys.c kernel/exit.c и arch/x86/kernel/apm.c
не полный ответ, но я думаю, что это хороший старт. Мне нужно будет прочитать мой машинный код BIOS, чтобы посмотреть, что они делают. но эта часть специфична для машины. maby, если вы знаете, что IC contol power на вашей материнской плате вы можете определить, какой порт ввода-вывода, зарегистрировать и команду вам нужно. затем настройте правильные состояния платы/устройств и затем выполните команду для выключения питания.
BIOS управляет мощностью через INT 15h ah = 53h (так называемое Advanced Power Management aka APM) Функция al = 07, используемая в Linux, - это заданное состояние мощности cmd. Параметры bx = 0001h означают, что все устройства и cx = 0003k означают остановку.
Ответ 5
Преобразование ответа @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
Сопротивление Nasm:
nasm -f bin -o boot_sect.img shutdown.asm
Файл конфигурации Bochs (имя файла:.bochsrc) в том же каталоге, что и код (shutdown.asm)
display_library: sdl
floppya: 1_44=boot_sect.img, status=inserted
boot: a
* Примечание. Я использую библиотеку sdl для bochs, которая представляет собой отдельный пакет из самих bochs
Запуск bochs (из того же каталога, что и раньше):
bochs
Нажмите, чтобы завершить работу
* Примечание. Я не уверен, что все строки между ярлыком Shutdown и ярлыком WaitForEnter необходимы
Ответ 6
Из 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);
}
}
Код теперь находится в apm_32.c. Найдите "apm_power_off".
Ответ 7
Это довольно легко. Кроме того, ребята, OP могут работать над своим собственным менеджером. То же самое, что я делаю. Это пример, который позволит пользователю выключить машину. Довольно просто, просто дает пользователю сообщение с ОК и Отмена. Если пользователь нажимает "ОК", машина выключится, если пользователь наберет отмену, программа просто выйдет. Он протестирован на версиях Windows на базе NT и должен работать с более старыми версиями, такими как ME, 95 и 98.
Это мой собственный код, и каждый может использовать его. http://pastebin.com/ccw3mWtw
Ответ 8
Вызвать функцию ExitWindowsEx API в файле kernel32.dll
Ответ 9
GRUB
$ bzr branch http://bzr.savannah.gnu.org/r/grub/trunk/grub
$ vi grub/grub-core/commands/acpihalt.c +303
или здесь, на зеркале Github:
https://github.com/dajhorn/grub/blob/trunk/grub/grub-core/commands/acpihalt.c#L303
Ответ 10
для 32-битной операционной системы, использующей этот код:
BITS 32
global _start
section .text
_start:
; Local variables:
;
; [ebp-4] Address of ntdll.dll
; [ebp-8] Address of ntdll.dll export table
; [ebp-12] Space for RtlAdjustPrivilege output
push ebp
mov ebp,esp
sub esp,12
; Save registers
push ebx
push esi
push edi
jmp get_delta_offset ; Get the delta offset
get_delta_offset2:
pop ebx
jmp start ; Jump to main code
get_delta_offset:
call get_delta_offset2
data:
NtShutdownSystem_s db "NtShutdownSystem"
NtShutdownSystem_len equ $-NtShutdownSystem_s
RtlAdjustPrivilege_s db "RtlAdjustPrivilege"
RtlAdjustPrivilege_len equ $-RtlAdjustPrivilege_s
get_function_address:
; Save registers
push ebx
push esi
push edi
mov eax,[ebp-8]
mov ebx,[eax+0x20] ; ebx now points to the export names array
add ebx,[ebp-4]
xor eax,eax
.get_function_address_loop:
mov esi,edx ; esi now points to the function
mov edi,[ebx+eax*4]
add edi,[ebp-4] ; edi now points to the export name
push ecx ; Save the function name length
cld ; Clear the direction flag
rep cmpsb ; Do the comparison
pop ecx ; Restore the length
je .get_function_address_end
inc eax
cmp eax,[ebx+0x14]
jl .get_function_address_loop
.get_function_address_fail:
pop edi
pop esi
pop ebx
xor eax,eax
ret
.get_function_address_end:
mov ebx,[ebp-8]
mov ecx,[ebx+0x1c]
add ecx,[ebp-4] ; ecx now points to the function addresses array
mov edx,[ebx+0x24]
add edx,[ebp-4] ; edx now points to the ordinals array
movzx eax,word [edx+eax*2] ; eax now holds the ordinal
mov eax,[ecx+eax*4] ; eax now holds the RVA of the function
add eax,[ebp-4] ; eax now holds the address of the function
; Restore registers
pop edi
pop esi
pop ebx
ret
start:
xor ecx,ecx
mov eax,[fs:ecx+0x30] ; eax now points to the PEB
mov eax,[eax+0xc] ; eax now points to loader data
mov eax,[eax+0x14]
mov eax,[eax+ecx]
mov eax,[eax+0x10] ; eax now holds the address of ntdll.dll
mov [ebp-4],eax ; Save the address of ntdll.dll
add eax,[eax+0x3c] ; eax now points to the PE header
mov eax,[eax+0x78] ; eax now points to the export directory
add eax,[ebp-4] ; eax now points to the export table
mov [ebp-8],eax
xor ecx,ecx
mov cl,NtShutdownSystem_len
mov edx,ebx
add ebx,ecx ; Move to next string
call get_function_address
test eax,eax
je exit
mov esi,eax
xor ecx,ecx
mov cl,RtlAdjustPrivilege_len
mov edx,ebx
call get_function_address
test eax,eax
je exit
mov edi,eax
xor eax,eax
; Enable SeShutdownPrivilege
lea ecx,[ebp-12]
push ecx
push eax ; CurrentThread = FALSE
push 1 ; Enable = TRUE
push 19 ; SeShutdownPrivilege
call edi ; Call RtlAdjustPrivilege
xor eax,eax
push eax ; ShutdownNoReboot
call esi ; Call NtShutdownSystem
exit:
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
ret