⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pm12a.asm

📁 《自己动手写操作系统》一书的光盘配套代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
								; pm12a.asm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	pm12a.asm - protected-mode demo code
;	Christopher Giese <geezer[AT]execpc.com>
;
;	Release date 9/28/98. Distribute freely. ABSOLUTELY NO WARRANTY.
;	Assemble pm12a.asm with NASM:
;				nasm -f aout -o pm12a.o pm12a.asm
;	Compile pm12c.c with DJGPP:
;				gcc -c -O2 -o pm12c.o pm12c.c
;	Link with DJGPP ld, using pm12.scr linker script:
;				ld -o pm12.com -Tpm12.scr pm12a.o pm12c.o
;	or just type:
;				make -f pm12.mak
;
; Demonstrates:
;	- Interface and linking to C-language code.
;	- The beginnings of a libc (standard C library).
;	- More elaborate syscalls and error-handling.
;	- Scrolling video; moving cursor in putch().
; Fixes/changes:
;	- Byte 6 of descriptors (flags/limit 19:16) changed from
;	  0xFC to 0xCF
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[SECTION .text]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	16-bit real mode
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[BITS 16]
[GLOBAL _start]			; DJGPP needs the underbars
; point code/data descriptors to CS<<4 (=DS<<4 for .COM file)
_start:	xor ebx,ebx
	mov bx,cs		; EBX=segment
	shl ebx,4		; EBX=segment << 4
	lea eax,[ebx]		; =linear address of segment base
	mov [gdt2 + 2],ax
	mov [gdt3 + 2],ax
	mov [gdt4 + 2],ax
	mov [gdt5 + 2],ax
	shr eax,16
	mov [gdt2 + 4],al
	mov [gdt3 + 4],al
	mov [gdt4 + 4],al
	mov [gdt5 + 4],al
	mov [gdt2 + 7],ah
	mov [gdt3 + 7],ah
	mov [gdt4 + 7],ah
	mov [gdt5 + 7],ah
; point tss descriptor to tss
	lea eax,[ebx + tss]	; EAX=linear address of tss
	mov [gdt6 + 2],ax
	shr eax,16
	mov [gdt6 + 4],al
	mov [gdt6 + 7],ah
; point gdtr to the gdt, idtr to the idt
	lea eax,[ebx + gdt]	; EAX=linear address of gdt
	mov [gdtr + 2],eax
	lea eax,[ebx + idt]	; EAX=linear address of idt
	mov [idtr + 2],eax
; clear NT bit (so iret does normal iret, instead of task-switch),
; set IOPL=00, and set IF=0 (disable interrupts)
	push dword 0
	popfd
; load GDT and IDT for full protected mode
	lgdt [gdtr]
	lidt [idtr]
; set PE [protected mode enable] bit and go
	mov eax,cr0
	or al,1
	mov cr0,eax
	jmp SYS_CODE_SEL:do_pm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	32-bit protected mode, ring 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[BITS 32]
[GLOBAL do_pm]
do_pm:	mov ax,SYS_DATA_SEL
	mov ds,ax
	mov ss,ax
	nop
	mov es,ax
	mov fs,ax
	mov gs,ax
; reprogram 8259-compatible interrupt controllers to use INT 20h through
; INT 2Fh for the 16 hardware interrupts. Code from Josh McDonald's OS/2000
; <http://www.effect.net.au/os-dev/> and from Linux.
	mov al,0x11		; put both 8259s in init mode
	out 0x20,al
	out 0xA0,al
	mov al,0x20		; IRQ0-IRQ7 -> interrupts 0x20-0x27
	out 0x21,al
	add al,8
	out 0xA1,al		; IRQ8-IRQ15 -> interrupts 0x28-0x2F
	mov al,4
	out 0x21,al
	mov al,2
	out 0xA1,al
	mov al,1
	out 0x21,al
	out 0xA1,al
; enable IRQs at these chips [ints still disabled at CPU]
	mov al,0xFE		; IRQ0 [timer]
	out 0x21,al
	mov al,0xFF		; none
	out 0xA1,al
; load task register. We don't use the x86 task switch mechanism, but
; we still need the TSS to specify the locations of the system-mode
; (Ring 0) and user-mode (Ring 3) stacks
	mov ax,USER_TSS
	ltr ax
; set up scheduler
	lea ebx,[regsA]		; point to user regs
; SAVE KERNEL REGS
sched:	push ebx
; save current ESP in TSS
		mov [tss_esp0],esp
; LOAD USER REGS
		lea esp,[ebx]
; pop EAX, EBX, ECX, EDX, EBP, ESI, EDI...
		popa
; ...DS, ES, FS, GS...
		pop ds
		pop es
		pop fs
		pop gs
; ...EIP, CS, EFLAGS, ESP, SS (jumps to user task)
		iret
; timer interrupt (IRQ0 = int 0x30) brings us back here
; XXX - how to validate hardware IRQ?
; user EIP, CS, EFLAGS, ESP, SS left on stack -- complete the stack frame
isr20:		push gs
		push fs
		push es
		push ds
		pusha
; reset 8259 interrupt controller
		mov al,0x20
		out 0x20,al
; SAVE USER REGS
		mov ax,ss
		mov ds,ax
		mov es,ax
		mov fs,ax
		mov gs,ax
		lea esi,[esp]
		mov edi,[esp + 68]	; saved kernel EBX -> user regs
		mov ecx,17		; 17 dwords worth (68 bytes)
		rep movsd
		add esp,68
; LOAD KERNEL REGS
	pop ebx
; reschedule
	cmp ebx,regsA
	je next
	lea ebx,[regsA]
	jmp sched
next:	lea ebx,[regsB]
	jmp sched
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	fault handlers (EIP -> offending instruction)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
isr0:	push dword 0
		jmp fault	; zero divide
isr5:	push dword 5
		jmp fault	; BOUND
isr6:	push dword 6
		jmp fault	; invalid opcode
isr7:	push dword 7
		jmp fault	; coprocessor not available
isr10:	push dword 0x10
		jmp fault
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	aborts (EIP = garbage)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
isr9:	push dword 9		; coprocessor segment overrun

fault:		mov ax,ss
		mov ds,ax
		mov es,ax
		mov fs,ax
		mov gs,ax
[EXTERN _unhand]
		call _unhand
		jmp $
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	fault handlers w/ error code (EIP -> offending instruction)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
isr0A:	push dword 0x0A
		jmp fault2	; bad TSS
isr0B:	push dword 0x0B
		jmp fault2	; segment not present
isr0C:	push dword 0x0C
		jmp fault2	; stack fault
isr0D:	push dword 0x0D
		jmp fault2	; GPF
isr0E:	push dword 0x0E
		jmp fault2	; page fault
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	aborts w/ error code (EIP = garbage)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
isr8:	push dword 8		; double fault

fault2:		mov ax,ss
		mov ds,ax
		mov es,ax
		mov fs,ax
		mov gs,ax
[EXTERN _unhand2]
		call _unhand2
		jmp $
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	traps (EIP -> beyond offending instruction)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
isr1:	push dword 1
		jmp fault	; debug (XXX - may be fault or trap)
isr2:	push dword 2
		jmp fault	; non-maskable interrupt
isr4:	push dword 4
		jmp fault	; INTO
isr3:	push dword 3
		jmp fault	; INT3
isr0F:	push dword 0x0F
		jmp fault	; coprocessor error
isr11:	push dword 0x11
		jmp fault	; alignment check
isr12:	push dword 0x12
		jmp fault
isr13:	push dword 0x13
		jmp fault
isr14:	push dword 0x14
		jmp fault
isr15:	push dword 0x15
		jmp fault
isr16:	push dword 0x16
		jmp fault
isr17:	push dword 0x17
		jmp fault
isr18:	push dword 0x18
		jmp fault
isr19:	push dword 0x19
		jmp fault
isr1A:	push dword 0x1A
		jmp fault
isr1B:	push dword 0x1B
		jmp fault
isr1C:	push dword 0x1C
		jmp fault
isr1D:	push dword 0x1D
		jmp fault
isr1E:	push dword 0x1E
		jmp fault
isr1F:	push dword 0x1F
		jmp fault
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	hardware interrupts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; isr20 (timer interrupt) handled above
isr21:	push dword 0x21
		jmp fault
isr22:	push dword 0x22
		jmp fault
isr23:	push dword 0x23
		jmp fault
isr24:	push dword 0x24
		jmp fault
isr25:	push dword 0x25
		jmp fault
isr26:	push dword 0x26
		jmp fault
isr27:	push dword 0x27
		jmp fault
isr28:	push dword 0x28
		jmp fault
isr29:	push dword 0x29
		jmp fault
isr2A:	push dword 0x2A
		jmp fault
isr2B:	push dword 0x2B
		jmp fault
isr2C:	push dword 0x2C
		jmp fault
isr2D:	push dword 0x2D
		jmp fault
isr2E:	push dword 0x2E
		jmp fault
isr2F:	push dword 0x2F
barf:		jmp fault
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	syscall interrupt
; 	Works when called from Ring 0 code or from Ring 3.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
isr30:	pusha
	push gs
	push fs
	push es
	push ds
; though possibly called from Ring 3, this code runs at Ring 0,
; and can use SYS_DATA_SEL and LINEAR_SEL
		mov bx,SYS_DATA_SEL
		mov ds,bx
		mov es,bx
		mov fs,bx
		mov gs,bx
; did we arrive here because of an INT 0x30 instruction?
		mov ebx,[48+esp]
		cmp word [ebx - 2],0x30CD
	;	push dword 0x30	; XXX - this validation doesn't work
; no, treat as unhandled interrupt
	;	jne barf
; yes, print char in al
		push eax
[EXTERN _putch]
			call _putch
		pop eax
	pop ds
	pop es
	pop fs
	pop gs
	popa
	iret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[GLOBAL _CsrX]
_CsrX:	db 0
[GLOBAL _CsrY]
_CsrY:	db 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	16-bit limit/32-bit linear base address of GDT and IDT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gdtr:	dw gdt_end - gdt - 1	; GDT limit
	dd gdt			; linear, physical address of GDT

idtr:	dw idt_end - idt - 1	; IDT limit
	dd idt			; linear, physical address of IDT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	global descriptor table (GDT)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; null descriptor
gdt:	dw 0			; limit 15:0
	dw 0			; base 15:0
	db 0			; base 23:16
	db 0			; type
	db 0			; limit 19:16, flags
	db 0			; base 31:24
; linear data segment descriptor
LINEAR_SEL	equ	$-gdt
	dw 0xFFFF		; limit 0xFFFFF
	dw 0			; base for this one is always 0
	db 0
	db 0x92			; present, ring 0, data, expand-up, writable
	db 0xCF			; page-granular, 32-bit
	db 0
; code segment descriptor
SYS_CODE_SEL	equ	$-gdt
gdt2:	dw 0xFFFF
	dw 0			; (base gets set above)
	db 0
	db 0x9A			; present, ring 0, code, non-conforming, readable
	db 0xCF
	db 0
; data segment descriptor
SYS_DATA_SEL	equ	$-gdt
gdt3:	dw 0xFFFF
	dw 0			; (base gets set above)
	db 0
	db 0x92			; present, ring 0, data, expand-up, writable
	db 0xCF
	db 0
; code segment descriptor
USER_CODE_SEL	equ	$-gdt+3
gdt4:	dw 0xFFFF
	dw 0			; (base gets set above)
	db 0
	db 0xFA			; present, ring 3, code, non-conforming, readable
	db 0xCF
	db 0

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -