📄 klib386.s
字号:
#
! sections
.sect .text; .sect .rom; .sect .data; .sect .bss
#include <minix/config.h>
#include <minix/const.h>
#include "const.h"
#include "sconst.h"
#include "protect.h"
! This file contains a number of assembly code utility routines needed by the
! kernel. They are:
.define _monitor ! exit Minix and return to the monitor
.define _check_mem ! check a block of memory, return the valid size
.define _cp_mess ! copies messages from source to destination
.define _exit ! dummy for library routines
.define __exit ! dummy for library routines
.define ___exit ! dummy for library routines
.define ___main ! dummy for GCC
.define _in_byte ! read a byte from a port and return it
.define _in_word ! read a word from a port and return it
.define _out_byte ! write a byte to a port
.define _out_word ! write a word to a port
.define _port_read ! transfer data from (disk controller) port to memory
.define _port_read_byte ! likewise byte by byte
.define _port_write ! transfer data from memory to (disk controller) port
.define _port_write_byte ! likewise byte by byte
.define _lock ! disable interrupts
.define _unlock ! enable interrupts
.define _enable_irq ! enable an irq at the 8259 controller
.define _disable_irq ! disable an irq
.define _phys_copy ! copy data from anywhere to anywhere in memory
.define _mem_rdw ! copy one word from [segment:offset]
.define _reset ! reset the system
.define _mem_vid_copy ! copy data to video ram
.define _vid_vid_copy ! move data in video ram
.define _level0 ! call a function at level 0
! The routines only guarantee to preserve the registers the C compiler
! expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and
! direction bit in the flags).
! imported variables
.sect .bss
.extern _mon_return, _mon_sp
.extern _irq_use
.extern _blank_color
.extern _ext_memsize
.extern _gdt
.extern _low_memsize
.extern _sizes
.extern _vid_seg
.extern _vid_size
.extern _vid_mask
.extern _level0_func
.sect .text
!*===========================================================================*
!* monitor *
!*===========================================================================*
! PUBLIC void monitor();
! Return to the monitor.
_monitor:
mov eax, (_reboot_code) ! address of new parameters
mov esp, (_mon_sp) ! restore monitor stack pointer
o16 mov dx, SS_SELECTOR ! monitor data segment
mov ds, dx
mov es, dx
mov fs, dx
mov gs, dx
mov ss, dx
pop edi
pop esi
pop ebp
o16 retf ! return to the monitor
#if ENABLE_BIOS_WINI
!*===========================================================================*
!* bios13 *
!*===========================================================================*
! PUBLIC void bios13();
.define _bios13
_bios13:
cmpb (_mon_return), 0 ! is the monitor there?
jnz 0f
movb (_Ax+1), 0x01 ! "invalid command"
ret
0: push ebp ! save C registers
push esi
push edi
push ebx
pushf ! save flags
cli ! no interruptions
inb INT2_CTLMASK
movb ah, al
inb INT_CTLMASK
push eax ! save interrupt masks
mov eax, (_irq_use) ! map of in-use IRQs
and eax, ~[1<<CLOCK_IRQ] ! there is a special clock handler
outb INT_CTLMASK ! enable all unused IRQs and vv.
movb al, ah
outb INT2_CTLMASK
mov eax, cr0
push eax ! save machine status word
mov eax, SS_SELECTOR ! monitor data segment
mov ss, ax
xchg esp, (_mon_sp) ! switch stacks
o16 push (_Es) ! parameters used in bios 13 call
o16 push (_Dx)
o16 push (_Cx)
o16 push (_Bx)
o16 push (_Ax)
mov ds, ax ! remaining data selectors
mov es, ax
mov fs, ax
mov gs, ax
push cs
push return ! kernel return address and selector
o16 jmpf 16+2*4+5*2+2*4(esp) ! make the call
return:
o16 pop (_Ax)
o16 pop (_Bx)
o16 pop (_Cx)
o16 pop (_Dx)
o16 pop (_Es)
lgdt (_gdt+GDT_SELECTOR) ! reload global descriptor table
jmpf CS_SELECTOR:csinit ! restore everything
csinit: mov eax, DS_SELECTOR
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
xchg esp, (_mon_sp) ! unswitch stacks
lidt (_gdt+IDT_SELECTOR) ! reload interrupt descriptor table
andb (_gdt+TSS_SELECTOR+DESC_ACCESS), ~0x02 ! clear TSS busy bit
mov ax, TSS_SELECTOR
ltr ax ! set TSS register
pop eax
mov cr0, eax ! restore machine status word
pop eax
outb INT_CTLMASK ! restore interrupt masks
movb al, ah
outb INT2_CTLMASK
popf ! restore flags
pop ebx ! restore C registers
pop edi
pop esi
pop ebp
ret
.sect .bss
.define _Ax, _Bx, _Cx, _Dx, _Es ! 8086 register variables
.comm _Ax, 4
.comm _Bx, 4
.comm _Cx, 4
.comm _Dx, 4
.comm _Es, 4
.sect .text
#endif /* ENABLE_BIOS_WINI */
!*===========================================================================*
!* check_mem *
!*===========================================================================*
! PUBLIC phys_bytes check_mem(phys_bytes base, phys_bytes size);
! Check a block of memory, return the amount valid.
! Only every 16th byte is checked.
! An initial size of 0 means everything.
! This really should do some alias checks.
CM_DENSITY = 16
CM_LOG_DENSITY = 4
TEST1PATTERN = 0x55 ! memory test pattern 1
TEST2PATTERN = 0xAA ! memory test pattern 2
CHKM_ARGS = 4 + 4 + 4 ! 4 + 4
! ds ebx eip base size
_check_mem:
push ebx
push ds
o16 mov ax, FLAT_DS_SELECTOR
mov ds, ax
mov eax, CHKM_ARGS(esp)
mov ebx, eax
mov ecx, CHKM_ARGS+4(esp)
shr ecx, CM_LOG_DENSITY
cm_loop:
movb dl, TEST1PATTERN
xchgb dl, (eax) ! write test pattern, remember original
xchgb dl, (eax) ! restore original, read test pattern
cmpb dl, TEST1PATTERN ! must agree if good real memory
jnz cm_exit ! if different, memory is unusable
movb dl, TEST2PATTERN
xchgb dl, (eax)
xchgb dl, (eax)
add eax, CM_DENSITY
cmpb dl, TEST2PATTERN
loopz cm_loop
cm_exit:
sub eax, ebx
pop ds
pop ebx
ret
!*===========================================================================*
!* cp_mess *
!*===========================================================================*
! PUBLIC void cp_mess(int src, phys_clicks src_clicks, vir_bytes src_offset,
! phys_clicks dst_clicks, vir_bytes dst_offset);
! This routine makes a fast copy of a message from anywhere in the address
! space to anywhere else. It also copies the source address provided as a
! parameter to the call into the first word of the destination message.
!
! Note that the message size, "Msize" is in DWORDS (not bytes) and must be set
! correctly. Changing the definition of message in the type file and not
! changing it here will lead to total disaster.
CM_ARGS = 4 + 4 + 4 + 4 + 4 ! 4 + 4 + 4 + 4 + 4
! es ds edi esi eip proc scl sof dcl dof
.align 16
_cp_mess:
cld
push esi
push edi
push ds
push es
mov eax, FLAT_DS_SELECTOR
mov ds, ax
mov es, ax
mov esi, CM_ARGS+4(esp) ! src clicks
shl esi, CLICK_SHIFT
add esi, CM_ARGS+4+4(esp) ! src offset
mov edi, CM_ARGS+4+4+4(esp) ! dst clicks
shl edi, CLICK_SHIFT
add edi, CM_ARGS+4+4+4+4(esp) ! dst offset
mov eax, CM_ARGS(esp) ! process number of sender
stos ! copy number of sender to dest message
add esi, 4 ! do not copy first word
mov ecx, Msize - 1 ! remember, first word does not count
rep
movs ! copy the message
pop es
pop ds
pop edi
pop esi
ret ! that is all folks!
!*===========================================================================*
!* exit *
!*===========================================================================*
! PUBLIC void exit();
! Some library routines use exit, so provide a dummy version.
! Actual calls to exit cannot occur in the kernel.
! GNU CC likes to call ___main from main() for nonobvious reasons.
_exit:
__exit:
___exit:
sti
jmp ___exit
___main:
ret
!*===========================================================================*
!* in_byte *
!*===========================================================================*
! PUBLIC unsigned in_byte(port_t port);
! Read an (unsigned) byte from the i/o port port and return it.
.align 16
_in_byte:
mov edx, 4(esp) ! port
sub eax, eax
inb dx ! read 1 byte
ret
!*===========================================================================*
!* in_word *
!*===========================================================================*
! PUBLIC unsigned in_word(port_t port);
! Read an (unsigned) word from the i/o port port and return it.
.align 16
_in_word:
mov edx, 4(esp) ! port
sub eax, eax
o16 in dx ! read 1 word
ret
!*===========================================================================*
!* out_byte *
!*===========================================================================*
! PUBLIC void out_byte(port_t port, u8_t value);
! Write value (cast to a byte) to the I/O port port.
.align 16
_out_byte:
mov edx, 4(esp) ! port
movb al, 4+4(esp) ! value
outb dx ! output 1 byte
ret
!*===========================================================================*
!* out_word *
!*===========================================================================*
! PUBLIC void out_word(Port_t port, U16_t value);
! Write value (cast to a word) to the I/O port port.
.align 16
_out_word:
mov edx, 4(esp) ! port
mov eax, 4+4(esp) ! value
o16 out dx ! output 1 word
ret
!*===========================================================================*
!* port_read *
!*===========================================================================*
! PUBLIC void port_read(port_t port, phys_bytes destination, unsigned bytcount);
! Transfer data from (hard disk controller) port to memory.
PR_ARGS = 4 + 4 + 4 ! 4 + 4 + 4
! es edi eip port dst len
.align 16
_port_read:
cld
push edi
push es
mov ecx, FLAT_DS_SELECTOR
mov es, cx
mov edx, PR_ARGS(esp) ! port to read from
mov edi, PR_ARGS+4(esp) ! destination addr
mov ecx, PR_ARGS+4+4(esp) ! byte count
shr ecx, 1 ! word count
rep ! (hardware cannot handle dwords)
o16 ins ! read everything
pop es
pop edi
ret
!*===========================================================================*
!* port_read_byte *
!*===========================================================================*
! PUBLIC void port_read_byte(port_t port, phys_bytes destination,
! unsigned bytcount);
! Transfer data from port to memory.
PR_ARGS_B = 4 + 4 + 4 ! 4 + 4 + 4
! es edi eip port dst len
_port_read_byte:
cld
push edi
push es
mov ecx, FLAT_DS_SELECTOR
mov es, cx
mov edx, PR_ARGS_B(esp)
mov edi, PR_ARGS_B+4(esp)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -