Я хочу отправлять команды на жесткий диск. Я осознаю, что жесткий диск должен быть готов к приему и отправке команд. Для следующего фрагмента кода, почему все возвращает 32 вместо 64 в защищенном режиме?
;no drive commands were executed before this code
mov dx,0x1F7
drive_loop:
in al, dx ;port input, result saved in al
bt eax, 7 ;checks if BSY is set
jc drive_loop ;jumps back if BSY is set
inc al ;checks if the answer is 32 by forcing it to display ! through incrementing al
mov [0xb8000], al
dec al
jmp $ ;al contains 32
Для минимально воспроизводимого примера
Загрузить: http://diamondmenmaster.com/Reproducible/Reproducible.zip
Полный код:
[org 0x7c00]
stack:
; Setup the stack away from our code.
not bp; Set the stack base (bottom)
mov sp, bp ; Set the stack top to the base (i.e. an empty stack)
init_pm:
cli;disables interrupts
lgdt [gdt_descriptor];setup the user data for protected mode
mov eax, cr0;moves cr0 register to the eax register
inc eax;increases the eax register by 1
mov cr0, eax;moves eax register to the cr0 register
mov ax, DATA_SEG;moves DATA_SEG to the eax register
;sets ax register to ds,ss,es,fs,gs registers
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 0x90000;Updates the stack position so it is right
mov esp, ebp;at the top of the free space.
jmp 08h:BEGIN_PM;starts protected mode with code starting at BEGIN_PM
[bits 32]
BEGIN_PM :
mov al,0x11;initialization sequence
out 0x20,al;sends ax register to 8259A-1
out 0xA0,al;and to 8259A-2
mov al,0x20;sets up the start of hardware interrupts (0x20)
out 0x21,al
mov al,0x28;sets up the start of hardware interrupts 2 (0x28)
out 0xA1,al
mov al,0x04;8259-1 is master
out 0x21,al
mov al,0x02; 8259-2 is slave
out 0xA1,al
mov al,0x01;8086 mode for both
out 0x21,al
out 0xA1,al
interrupt_setup:
mov eax,[idt_start];moves half of the interrupt descriptor for a interrupt to the eax register
mov edx,[idt_start + 4];moves the other half of the interrupt descriptor to the edx register
mov ecx,0x20*8;moves the location of the interrupt descriptor for the timer device to the ecx register
mov [ecx],eax;moves eax register to the location stored in the ecx register
;increments ecx by 1 by four times
inc ecx
inc ecx
inc ecx
inc ecx
mov [ecx],edx;moves edx register to the location stored in the ecx register
mov ecx,0x21*8;moves the location of the interrupt descriptor for the keyboard device to the ecx register
mov ax,Key_Handler;moves the location of Keyboard interrupt handler to the ecx register
mov [ecx],eax;moves eax register to the location stored in the ecx register
;increments ecx by 1 by four times
inc ecx
inc ecx
inc ecx
inc ecx
mov [ecx],edx;moves edx register to the location stored in the ecx register
sti;enables interrupts
repeat:
hlt;waits for any device interrupts
jmp repeat;jumps back to wait again
Interput_Handler:;handles the timer interrupts
mov al,0x20
out 0x20,al;lets devices know that the os is ready to receive another interrupt
iret;returns from the interrupt routine
Key_Handler:;handles the keyboard interrupts
;no drive commands were executed before this code
mov dx,0x1F7
drive_loop:
in al, dx ;port input, result saved in al
bt eax, 7 ;checks if BSY is set
jc drive_loop ;jumps back if BSY is set
inc al ;checks if the answer is 32 by forcing it to display ! through incrementing al
mov [0xb8000], al
dec al
jmp $ ;al contains 32
mov al,0x20
out 0x20,al;lets devices know that the os is ready to receive another interrupt
iret;returns from the interrupt routine
Data:
idt_start:
dw Interput_Handler
dw CODE_SEG
db 0x0
db 0b11101111
dw 0x00
gdt_start:
gdt_null: ; the mandatory null descriptor
dd 0x0
dd 0x0
gdt_code: ; the code segment descriptor
dw 0xffff
dw 0x0
db 0x0
db 10011010b
db 11001111b
db 0x0
gdt_data: ; the data segment descriptor
dw 0xffff
dw 0x0
db 0x0
db 10010010b
db 11001111b
db 0x0
gdt_end:
gdt_descriptor:
dw gdt_end - gdt_start - 1
dd gdt_start
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
; Pad out the boot sector to 512 bytes with last 2 bytes as verification number.
times 510-($-$$) db 0
dw 0xaa55