?? boothead.s
字號(hào):
int 0x16 jnz getc ! Keypress? xor ax, ax ! No key ret_getchar: movb ah, #0 ! Read character from keyboard int 0x16getc: cmpb al, #0x3D ! '=' character jnz noeq movb _eqscancode, ah ! Save scancode of '=' keynoeq: cmpb al, #0x0D ! Carriage return jnz nocr movb al, #0x0A ! Change to linefeednocr: xorb ah, ah ! ax = al ret! int putchar(c);! Write a character in teletype mode. The putc and putk synonyms! are for the kernel printk function that uses one of them.! Newlines are automatically prepended by a carriage return.!.define _putchar, _putc, _putk_putchar:_putc:_putk: mov bx, sp movb al, 2(bx) ! al = character to be printed testb al, al ! 1.6.* printk prints null characters jz nulch ! that appear as blanks, so don't do it. cmpb al, #0x0A ! al = newline? jnz putc ! No cmpb wdirty, #0 ! Yes, erase wheel and do a carriage return jz nodirt movb al, #0x20 ! putc(' '); call putcnodirt: movb al, #0x0D ! putc('\r') call putc movb al, #0x0A ! Restore the '\n' and print itputc: movb ah, #14 ! 14 = print character in teletype mode mov bx, #0x0001 ! Page 0, foreground color int 0x10 ! Call BIOS VIDEO_IO movb wdirty, #0nulch: ret! |/-\|/-\|/-\|/-\|/-\ (playtime)wheel: push si mov si, gp ! si = gp lodsb call putc ! putc(*si++) movb al, #0x08 call putc ! putc('\b') cmp si, #glyphs+4 jne wmore mov si, #glyphswmore: mov gp, si ! gp= si == glyphs + 4 ? glyphs : si; incb wdirty pop si ret.data .align 2gp: .data2 glyphsglyphs: .ascii "|/-\\"wdirty: .data1 0.text! void reset_video(int color);! Reset and clear the screen.! void set_cursor(column, row);! Position the cursor at a specified column & row..define _reset_video, _set_cursor_reset_video: mov bx, sp movb al, #7 ! Assume mode 7: 80x24 monochrome cmp 2(bx), #0 ! Or is color requested? jz clear movb al, #2 ! Mode 2: 80x25 colorclear: xorb ah, ah ! Reset video int 0x10 xor dx, dx ! dl = column = 0, dh = row = 0 jmp setcur_set_cursor: mov bx, sp movb dl, 2(bx) ! dl = column movb dh, 4(bx) ! dh = rowsetcur: xorb bh, bh ! Page 0 movb ah, #0x02 ! Set cursor position int 0x10 ret! u32_t get_tick(void);! Return the current value of the clock tick counter. This counter! increments 18.2 times per second. Poll it to do delays. Does not! work on the original PC, but works on the PC/XT..define _get_tick_get_tick: xorb ah, ah ! Code for get tick count int 0x1A mov ax, dx mov dx, cx ! dx:ax = cx:dx = tick count ret! Functions used to obtain info about the hardware, like the type of video! and amount of memory. Boot uses this information itself, but will also! pass them on to a pure 386 kernel, because one can't make BIOS calls from! protected mode. The video type could probably be determined by the kernel! too by looking at the hardware, but there is a small chance on errors that! the monitor allows you to correct by setting variables..define _get_video ! returns type of display.define _get_ext_memsize ! returns amount of extended memory in K.define _get_low_memsize ! returns amount of low memory in K.define _get_processor ! returns processor type (86, 186, 286, 386)! u16_t get_video(void)! Return type of display, in order: MDA, CGA, mono EGA, color EGA,! mono VGA, color VGA._get_video: mov ax, #0x1A00 ! Function 1A returns display code int 0x10 ! al = 1A if supported cmpb al, #0x1A jnz no_dc ! No display code function supported mov ax, #2 cmpb bl, #5 ! Is it a monochrome EGA? jz got_video inc ax cmpb bl, #4 ! Is it a color EGA? jz got_video inc ax cmpb bl, #7 ! Is it a monochrome VGA? jz got_video inc ax cmpb bl, #8 ! Is it a color VGA? jz got_videono_dc: movb ah, #0x12 ! Get information about the EGA movb bl, #0x10 int 0x10 cmpb bl, #0x10 ! Did it come back as 0x10? (No EGA) jz no_ega mov ax, #2 cmpb bh, #1 ! Is it monochrome? jz got_video inc ax jmp got_videono_ega: int 0x11 ! Get bit pattern for equipment and ax, #0x30 ! Isolate color/mono field sub ax, #0x30 jz got_video ! Is it an MDA? mov ax, #1 ! No it's CGAgot_video: ret! u16_t get_ext_memsize(void);! Ask the BIOS how much extended memory there is._get_ext_memsize: call _get_processor ! Is this an old crate? cmp ax, #186 jbe no_ext ! Don't try the next function, it crashed an XT movb ah, #0x88 clc ! Carry will stay clear if call exists int 0x15 ! Returns size (in K) in ax for AT's jnb got_ext_memsizeno_ext: sub ax, ax ! Error, probably a PCgot_ext_memsize: ret! u16_t get_low_memsize(void);! Ask the BIOS how much normal memory there is._get_low_memsize: int 0x12 ! Returns the size (in K) in ax ret! u16_t get_processor(void);! Decide processor type among 8088=8086, 80188=80186, 80286, 80386, 80486.! Return 86, 186, 286, 386 or 486.! Preserves all registers except the flags and the return register ax.! Method:! 8088=8086 and 80188=80186 push sp as new sp, 80286 and 80386 as old sp.! All but 8088=8086 do shifts mod 32 or 16.! 386 stores 0 for the upper 8 bits of the GDT pointer in 16 bit mode,! while 286 stores 0xFF.! 486 has an AC flag the 386 doesn't have. o32 = 0x66 ! 32 bit operand size prefix_get_processor: push bp mov bp, sp push sp ! see if pushed sp == sp pop ax cmp ax, sp jz new_processor mov cx, #0x0120 ! see if shifts are mod 32 shlb ch, cl ! zero tells if 86 mov ax, #86 jz got_processor mov ax, #186 jmp got_processornew_processor: ! see if high bits are set in saved GDT sub sp, #6 ! space for GDT ptr .data1 0x0F ! Prefix for 286 instruction: sgdt -6(bp) add -6(bp), ax ! save 3 word GDT ptr (This is NOT an add!) cmpb -1(bp), #0 ! top byte of GDT ptr is zero only for 386 mov ax, #286 jnz got_processor! 386 or 486 and sp, #0xFFFC ! Align stack to avoid AC fault (needed?) .data1 o32 ! About to operate on a 32 bit object pushf ! Push eflags pop ax pop dx ! dx:ax = eflags mov bx, ax mov cx, dx ! Save original eflags xor dx, #0x0004 ! Flip the AC bit push dx push ax ! Push modified eflags value .data1 o32 popf ! Load modified eflags register .data1 o32 pushf pop ax pop dx ! Get it again push cx push bx .data1 o32 popf ! Restore original eflags register xor dx, cx ! See if AC bit changed test dx, #0x0004 mov ax, #386 ! 386 if it didn't react to "flipping" jz got_processor mov ax, #486 ! 486 if you can modify the AC bitgot_processor: mov sp, bp pop bp ret! void _bootstrap(device, partoff, partseg)! Call another bootstrap routine to boot MS-DOS for instance. (No real! need for that anymore, now that you can format floppies under Minix).! The bootstrap must have been loaded at BOOTSEG from "device"..define _bootstrap_bootstrap: mov bx, sp movb dl, 2(bx) ! Device to boot from lds si, 4(bx) ! ds:si = partition table entry xor ax, ax mov es, ax ! Vector segment mov di, #BUFFER ! es:di = buffer in low core mov cx, #PENTRYSIZE ! cx = size of partition table entry rep movsb ! Copy the entry to low core mov si, #BUFFER ! es:si = partition table entry mov ds, ax ! Some bootstraps need zero segment registers cli mov ss, ax mov sp, #BOOTOFF ! This should do it sti jmpf BOOTOFF, 0 ! Back to where the BIOS loads the boot code! To my surprise this code is so fast that floppy drive 0 was still running! (tries to boot floppy first), when Minix was started after a hard disk boot.stop_motor: mov dx, #0x03F2 ! Motor drive control bits movb al, #0x0C ! Bits 4-7 for floppy 0-3 are off outb ! Kill the motors ret! void minix86(koff, kcs, kds, bootparams, paramsize);! Call 8086 Minix or 386 Minix with an 8086 startoff..define _minix86_minix86: call stop_motor ! Turn off floppy drives mov bp, sp ! Pointer to arguments mov ax, #0x100 ! Newer boot code mov si, 8(bp) mov di, ds ! di:si = boot parameters mov cx, 10(bp) ! # bytes of boot parameters push cx push si ! Kernel may find these on the stack too mov ds, 6(bp) ! Kernel data segment set mov es, 6(bp) ! Set es to kernel data too cli ! Disable interrupts jmpf @2(bp) ! Finally out of this mess!! Minix is called with ax, di and si as expected, but also with segment! registers and stack compatible with the 386 call.! void minix386(koff, kcs, kds, bootparams, paramsize);! Call 386 Minix with a 386 mode switch. Code inspired by the Amoeba! 386 bootstrap by Leendert van Doorn..define _minix386_minix386: call stop_motor ! Turn off floppy drives mov bp, sp ! Pointer to arguments mov di, ds ! Monitor ds mov si, #gdt ! di:si = Global descriptor table mov bx, #gdt_desc call set_base ! Set base of gdt descriptor mov di, 6(bp) ! Kernel ds xor si, si ! di:si = Kernel data segment mov bx, #ds_desc call set_base ! Set base of kernel ds mov di, ss ! Monitor ss xor si, si ! di:si = Monitor stack segment mov bx, #ss_desc call set_base ! Minix starts with the stack of the monitor mov di, 4(bp) ! Kernel cs xor si, si ! di:si = Kernel text segment mov bx, #cs_desc call set_base ! Set base of kernel cs xor ax, ax push ax push 10(bp) ! 32 bit size of parameters on stack push ax push 8(bp) ! 32 bit address of parameters (ss relative)! Use the BIOS to kick us into protected mode. This is the most portable! way to enable the A20 address line. A real programmer would use cr0. mov si, #gdt ! es:si = global descriptor table xor bx, bx ! 8259's must be initialized by the kernel movb ah, #0x89 ! Protected mode function code! Fake an interrupt stack frame as if called from the kernel entry point cli ! No more interruptions pushf ! Flags push 4(bp) ! Kernel cs push 2(bp) ! Kernel entry point mov ds, bx ! ds = vector segment jmpf @4*0x15 ! "int 0x15"! The "interrupt" will return directly to the Minix kernel in 386 mode. The! split is clean: No 386 code here, and no 8086 code in the kernel. The! boot parameters address and size are on the stack. They may be retrieved! using the ss descriptor.set_base: ! Set the base of descriptor bx to the 8086 address di:si mov 2(bx), di ! Base = segment mov cx, #4seg2abs: shl 2(bx), #1 rclb 4(bx), #1 ! Base = segment << 4 loop seg2abs add 2(bx), si adcb 4(bx), #0 ! Base = (segment << 4) + offset ret.data .align 2 UNSET = 0 ! Must be computed! Global descriptor table.gdt:null_desc: ! Null descriptor .data2 0x0000, 0x0000 .data1 0x00, 0x00, 0x00, 0x00gdt_desc: ! Descriptor for this descriptor table .data2 8*8-1, UNSET .data1 UNSET, 0x00, 0x00, 0x00idt_desc: ! Interrupt descriptor table descriptor (no interrupts allowed) .data2 0x0000, 0x0000 .data1 0x00, 0x00, 0x00, 0x00ds_desc: ! Kernel data segment descriptor (4Gb flat) .data2 0xFFFF, UNSET .data1 UNSET, 0x92, 0xCF, 0x00es_desc: ! Physical memory descriptor (4Gb flat) .data2 0xFFFF, 0x0000 .data1 0x00, 0x92, 0xCF, 0x00ss_desc: ! Monitor data segment descriptor (64Kb flat) .data2 0xFFFF, UNSET .data1 UNSET, 0x92, 0x40, 0x00cs_desc: ! Kernel code segment descriptor (4Gb flat) .data2 0xFFFF, UNSET .data1 UNSET, 0x9A, 0xCF, 0x00bios_desc: ! BIOS segment descriptor (scratch for int 0x15) .data2 UNSET, UNSET .data1 UNSET, UNSET, UNSET, UNSET
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -