Здравствуйте! Вопрос, собственно, в заголовке. Есть ли способ вырубить комп с помощью функций/прерываний/манипуляций с портами DOS/BIOS? Или это на каждой материнке/BIOS'е по-своему? Спасибо!
Посмотри int 15, ah=53h. У Ральфа Брауна все описания есть. Также можно гугол-> advanced power management.
.... message db 'Теперь питание компьютера можно выключить!',0dh,0ah,'$' ..... mov ah,9 mov dx,offset message int 21h
Интересный вопрос. Если посмотреть как это делает хал. Он даже может считать состояние кнопки "Power" системника. Ребут или выключение выполняется посредством HalReturnToFirmware(). Если это ребут, то всё просто - запись в системный порт 0x64 значения 0xFE, что приведёт к сбросу процессора. После подготовки к сбросу в HalpReboot() вызывается HalpWriteResetCommand(), которая собственно и выполняет сброс/выключает ибп: Код (Text): 003668C0 _HalpWriteResetCommand@0 /$ 33C9 xor ecx,ecx 003668C2 |. 41 inc ecx 003668C3 |. 380D 48263700 cmp byte ptr ds:[372648],cl 003668C9 |. 0F86 9A000000 jbe hal.00366969 003668CF |. F605 B1263700 0>test byte ptr ds:[3726B1],4 003668D6 |. 0F84 8D000000 je hal.00366969 003668DC |. 380D 48343700 cmp byte ptr ds:[_HalpMustUseResetReg],cl 003668E2 |. 74 09 je short hal.003668ED 003668E4 |. F605 AD263700 0>test byte ptr ds:[3726AD],2 003668EB |. 75 7C jnz short hal.00366969 003668ED |> 0FB605 B4263700 movzx eax,byte ptr ds:[3726B4] 003668F4 |. 83E8 00 sub eax,0 ; Switch (cases 0..2) 003668F7 |. 74 4E je short hal.00366947 003668F9 |. 48 dec eax 003668FA |. 74 36 je short hal.00366932 003668FC |. 48 dec eax 003668FD |. 75 6A jnz short hal.00366969 003668FF |. A1 B8263700 mov eax,dword ptr ds:[3726B8] ; Case 2 of switch 003668F4 00366904 |. 51 push ecx ; /Arg6 00366905 |. 8BC8 mov ecx,eax ; | 00366907 |. 81E1 FF000000 and ecx,0FF ; | 0036690D |. 51 push ecx ; |Arg5 0036690E |. 8B0D BC263700 mov ecx,dword ptr ds:[3726BC] ; | 00366914 |. C1E8 0B shr eax,0B ; | 00366917 |. 68 C0263700 push hal.003726C0 ; |Arg4 = 003726C0 0036691C |. 25 E0000000 and eax,0E0 ; | 00366921 |. 83E1 1F and ecx,1F ; | 00366924 |. 0BC1 or eax,ecx ; | 00366926 |. 50 push eax ; |Arg3 00366927 |. 6A 00 push 0 ; |Arg2 = 00000000 00366929 |. 6A 05 push 5 ; |Arg1 = 00000005 0036692B |. E8 1E060000 call hal.HalSetBusDataByOffset ; \HalSetBusDataByOffset 00366930 |. EB 37 jmp short hal.00366969 00366932 |> 33C0 xor eax,eax ; Case 1 of switch 003668F4 00366934 |. A0 C0263700 mov al,byte ptr ds:[3726C0] 00366939 |. 50 push eax 0036693A |. FF35 B8263700 push dword ptr ds:[3726B8] 00366940 |. E8 77210000 call hal.WRITE_PORT_UCHAR 00366945 |. EB 22 jmp short hal.00366969 00366947 |> 51 push ecx ; /Arg3; Case 0 of switch 003668F4 00366948 |. FF35 BC263700 push dword ptr ds:[3726BC] ; |Arg2 = 00000000 0036694E |. FF35 B8263700 push dword ptr ds:[3726B8] ; |Arg1 = 00000000 00366954 |. E8 D1100000 call hal._HalpMapPhysicalMemoryWriteThrough64@12 ; \_HalpMapPhysicalMemoryWriteThrough64@12 00366959 |. 33C9 xor ecx,ecx 0036695B |. 8A0D C0263700 mov cl,byte ptr ds:[3726C0] 00366961 |. 51 push ecx 00366962 |. 50 push eax 00366963 |. FF15 A8053600 call dword ptr ds:[<&ntoskrnl.WRITE_REGISTER_UCHAR>] ; ntoskrnl.WRITE_REGISTER_UCHAR 00366969 |> 68 FE000000 push 0FE ; Default case of switch 003668F4 0036696E |. 6A 64 push 64 00366970 |. E8 47210000 call hal.WRITE_PORT_UCHAR 00366975 \. C3 ret К сожалению этот код нельзя продебажить сисером, возможно wmware + windbg поможет. Параметр для той функции является одним из следующих: Код (Text): { HalHaltRoutine, HalPowerDownRoutine, HalRestartRoutine, HalRebootRoutine, HalInteractiveModeRoutine, Именно HalPowerDownRoutine и выключает питание. В приведённом дизасме это исполнит запись в порт: Код (Text): 00366932 |> \33C0 xor eax,eax ; Case 1 of switch 003668F4 00366934 |. A0 C0263700 mov al,byte ptr ds:[3726C0] 00366939 |. 50 push eax 0036693A |. FF35 B8263700 push dword ptr ds:[3726B8] 00366940 |. E8 77210000 call hal.WRITE_PORT_UCHAR ] Как видно порт не является константой, также это не проекция пространства регистров IO. Порт определяется(и не только этот) при инициализации хал наверно в функции HalpSetupAcpiPhase0(). Но не понятно, тот массив содержит нули, если система не готовится к выключению. Код весьма сложен, сурцов нет, максимум это реактос, теже сурцы винды , но так как это закрытый майкрософт код, в реактос нет кода выключающего питание. http://www.reactos.org/generated/doxygen/da/d40/haltypes_8h.html http://www.reactos.org/pipermail/ros-diffs/2006-November/014541.html Должно изучить матчать, это единственный вариант, который позволит понять как исполняется выключение атх.
Посмотри спецификацию на APM. Всё там просто (относительно). Clerk просто ядро с ACPI в отладчике смотрел, а с ACPI там действительно не всё так просто. Хотя тоже ничего сверхъестественного нету. Вообще говоря и через ACPI можно в три команды машину выключить, но будет зависимо от чипсета. А чтоб было независимо - надо таблицы ACPI парсить. В общем APM самый простой способ - раза три вызовеш int 15h и выключишь. APM BIOS Interface Specification Revision 1.2
А вот и примерчик Код (Text): POWER_OFF mov ax, 0x5301 xor bx, bx int 0x15 mov ax, 0x5308 mov bx, 1 mov cx, bx int 0x15 mov ax, 0x530D mov bx, 1 mov cx, bx int 0x15 mov ax, 0x530F mov bx, 1 mov cx, bx int 0x15 mov ax, 0x530E xor bx, bx mov cx, 0x102 int 15h mov ax, 0x5307 mov bx, 1 mov cx, 3 int 0x15 jmp $