📄 klib386.s
字号:
# ! sections.sect .text; .sect .rom; .sect .data; .sect .bss#include <minix/config.h>#include <minix/const.h>#include <ibm/interrupt.h>#include <archconst.h>#include "../../const.h"#include "sconst.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 _int86 ! let the monitor make an 8086 interrupt call.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 _phys_insw ! transfer data from (disk controller) port to memory.define _phys_insb ! likewise byte by byte.define _phys_outsw ! transfer data from memory to (disk controller) port.define _phys_outsb ! likewise byte by byte.define _intr_unmask ! enable an irq at the 8259 controller.define _intr_mask ! disable an irq.define _phys_copy ! copy data from anywhere to anywhere in memory.define _phys_memset ! write pattern anywhere in memory.define _mem_rdw ! copy one word from [segment:offset].define _reset ! reset the system.define _idle_task ! task executed when there is no work.define _level0 ! call a function at level 0.define _read_cpu_flags ! read the cpu flags.define _read_cr0 ! read cr0.define _write_cr0 ! write a value in cr0.define _write_cr3 ! write a value in cr3 (root of the page table)! 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)..sect .text!*===========================================================================*!* monitor *!*===========================================================================*! PUBLIC void monitor();! Return to the monitor._monitor: 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!*===========================================================================*!* int86 *!*===========================================================================*! PUBLIC void int86();_int86: cmpb (_mon_return), 0 ! is the monitor there? jnz 0f movb ah, 0x01 ! an int 13 error seems appropriate movb (_reg86+ 0), ah ! reg86.w.f = 1 (set carry flag) movb (_reg86+13), ah ! reg86.b.ah = 0x01 = "invalid command" ret0: 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 IRQ's and eax, ~[1<<CLOCK_IRQ] ! keep the clock ticking outb INT_CTLMASK ! enable all unused IRQ's and vv. movb al, ah outb INT2_CTLMASK mov eax, SS_SELECTOR ! monitor data segment mov ss, ax xchg esp, (_mon_sp) ! switch stacks push (_reg86+36) ! parameters used in INT call push (_reg86+32) push (_reg86+28) push (_reg86+24) push (_reg86+20) push (_reg86+16) push (_reg86+12) push (_reg86+ 8) push (_reg86+ 4) push (_reg86+ 0) 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 20+2*4+10*4+2*4(esp) ! make the callreturn: pop (_reg86+ 0) pop (_reg86+ 4) pop (_reg86+ 8) pop (_reg86+12) pop (_reg86+16) pop (_reg86+20) pop (_reg86+24) pop (_reg86+28) pop (_reg86+32) pop (_reg86+36) lgdt (_gdt+GDT_SELECTOR) ! reload global descriptor table jmpf CS_SELECTOR:csinit ! restore everythingcsinit: 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 eax, TSS_SELECTOR ltr ax ! set TSS register pop eax outb INT_CTLMASK ! restore interrupt masks movb al, ah outb INT2_CTLMASK add (_lost_ticks), ecx ! record lost clock ticks popf ! restore flags pop ebx ! restore C registers pop edi pop esi pop ebp 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!*===========================================================================*!* phys_insw *!*===========================================================================*! PUBLIC void phys_insw(Port_t port, phys_bytes buf, size_t count);! Input an array from an I/O port. Absolute address version of insw()._phys_insw: push ebp mov ebp, esp cld push edi push es mov ecx, FLAT_DS_SELECTOR mov es, cx mov edx, 8(ebp) ! port to read from mov edi, 12(ebp) ! destination addr mov ecx, 16(ebp) ! byte count shr ecx, 1 ! word countrep o16 ins ! input many words pop es pop edi pop ebp ret!*===========================================================================*!* phys_insb *!*===========================================================================*! PUBLIC void phys_insb(Port_t port, phys_bytes buf, size_t count);! Input an array from an I/O port. Absolute address version of insb()._phys_insb: push ebp mov ebp, esp cld push edi push es mov ecx, FLAT_DS_SELECTOR mov es, cx mov edx, 8(ebp) ! port to read from mov edi, 12(ebp) ! destination addr mov ecx, 16(ebp) ! byte count! shr ecx, 1 ! word count rep insb ! input many bytes pop es pop edi pop ebp ret!*===========================================================================*!* phys_outsw *!*===========================================================================*! PUBLIC void phys_outsw(Port_t port, phys_bytes buf, size_t count);! Output an array to an I/O port. Absolute address version of outsw(). .align 16_phys_outsw: push ebp mov ebp, esp cld push esi push ds mov ecx, FLAT_DS_SELECTOR mov ds, cx mov edx, 8(ebp) ! port to write to mov esi, 12(ebp) ! source addr mov ecx, 16(ebp) ! byte count shr ecx, 1 ! word countrep o16 outs ! output many words pop ds pop esi pop ebp ret!*===========================================================================*!* phys_outsb *!*===========================================================================*! PUBLIC void phys_outsb(Port_t port, phys_bytes buf, size_t count);! Output an array to an I/O port. Absolute address version of outsb().
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -