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

📄 entry.asm

📁 ucos在x86上的移植代码。吐血推荐啊
💻 ASM
字号:
; entry.asm :
; 		内核入口代码, 32位ELF, Protected Mode
;
; Copyright(c) 2007, Alex P.Wonder
; phoenixwonder@gmail.com
;

%include "pm.inc"

SelectorCode32 equ 0x0008

[SECTION .idt]
LABEL_IDT: ;中断描述符表
%rep 32
	Gate SelectorCode32, SpuriousHandler, DA_386IGate
%endrep

.020h:
	Gate SelectorCode32, SpuriousHandler, DA_386IGate

%rep 95
	Gate SelectorCode32, SpuriousHandler, DA_386IGate
%endrep
.080h:
	Gate SelectorCode32, MyIntHandler, DA_386IGate

IdtLen equ $ - LABEL_IDT
IdtPtr 	dw IdtLen		;段界限
				dd 0				;段基址
; End of [SECTION .idt]

[SECTION .text]

extern main
;extern myprint

;
; 系统内核入口:
;     在此之前,中断是被屏蔽掉的(从进入保护模式那一刻开始). 因此,
;	系统入口首先需要做的就是建立在保护模式下的完整的中断机制, 并为
; 多任务管理设置一个定时时钟, 作为任务切换的标准.
;
global _start
_start:
	mov			ah, 0x0f
	mov			al, 'V'
	mov			[gs:((80*11+0)*2)], ax
	
	
	; --重建保护模式下的中断机制--
	xor eax, eax

	mov eax, LABEL_IDT
	mov dword[IdtPtr + 2], eax
	cli
	lidt [IdtPtr] ;加载IDTR

	call Init8259A ;初始化8259芯片

;	mov ax, 0x36 ;C0, MODE3, BIN
;	out 0x43, ax
;	mov ax, 9c
;	out 0x40, al
;	mov ax, 2e
;	out 0x40, al

	; 现在可以开中断了:-)
	sti

	; 内核系统循环开始
	jmp main

	;call myprint
	;jmp $


;=========================================================
;											子调用函数
;=========================================================
global enable_8259_irq ;允许8259外部中断
enable_8259_irq:
	cli
	call Init8259A
	sti
	ret

Init8259A:
	mov 		al, 011h 	;ICW1, 主片8259a
	out			020h, al
	call		io_delay

	out			0a0h, al 	;ICW1, 从片8259a
	call		io_delay

	mov			al, 020h 	;ICW2,主片, IRQ0对应中断向量0x20, ..IRQ7->0x27
	out			021h, al
	call		io_delay

	mov			al, 028h	;ICW2,从片,IRQ8对应中断向量0x28, ..IRQ15->0x2f
	out			0a1h, al
	call		io_delay

	mov			al, 004h 	;ICW3,主片,IRQ2对应从8259
	out			021h, al
	call		io_delay

	mov			al, 002h	;ICW3,从片,对应主片的IRQ2
	out			0a1h, al
	call		io_delay

	mov			al, 001h	;ICW4,主片,x86模式
	out			021h, al
	call		io_delay

	out			0a1h, al	;ICW4,从片,x86模式
	call		io_delay

	mov			al, 1111000b ; 屏蔽主8259所有中断, 除定时器中断和键盘中断
	mov     al, 0x00
	out			021h, al ;主片OCW1
	call		io_delay

	mov			al, 11101111b ;屏蔽从8259所有中断, 除PS/2鼠标(IRQ12)
	out			0a1h, al ;从片OCW1
	call		io_delay
	ret

io_delay:
	nop
	nop
	nop
	nop
	ret

;==================================================================
; C格 式: void os_setvect(int vectno, void (*isr)(void))
; 说  明:
;
; 参  数:
;		vectno -- 中断ID号
;		isr		 -- 欲设置的中断服务程序地址
; 返回值:
;
;==================================================================
global os_setvect
os_setvect:
	push ebp
	mov  ebp, esp

	push eax
	push ebx
	pushfd
	cli ;关中断, 开始设置

	mov ebx, LABEL_IDT ;取IDT表基址

	xor eax, eax
	mov eax, [ebp + 8] ;vectno
	shl eax, 3 ; vectno*8是第vectno号中断描述符在IDT中的偏移位置
	add ebx, eax ; 第vectno号中断描述符在段内的偏移位置

	; 此时, ebx已经指向vectno对应中断的中断描述符了.
	; 下面就可以开始更改此描述符中的内容,即更改中断处理程序。
	; [中断/陷阱门结构]:
	;   %1 - Selector(中断程序所在的段选择子)
	;		%2 - HandlerAddr (驱动程序在段内的地址)
	;		%3 - Attribute (中断属性)
	;
	;	dw %2 & 0ffffh ; 0..15
	;	dw %1
	;	dw (%3 & 0ff00h)
	;	dw (%2 >> 16) & 0ffffh ; 16..31

	mov eax, dword [ebp + 12] ;isr

	mov word [ebx], ax ; dw %2 & 0ffffh ; 0..15
	shr eax, 16 ; dw (%2 >> 16) & 0ffffh ; 16..31
	mov word [ebx + 6], ax

	mov ax, cs ; 当前代码段作为selector
	mov word [ebx + 2], ax

	mov ax, 0x8e00 ; DA_386IGate
	mov word [ebx + 4], ax

	popfd ;恢复原来的中断处理状态
	pop ebx
	pop eax

	leave
	ret

;==================================================================
; C格 式: void *os_getvect(int vectno)
; 说  明:
;
; 参  数:
;		vectno -- 中断ID号
; 返回值:
;
;==================================================================
global os_getvect
os_getvect:
	push ebp
	mov  ebp, esp

	push ebx
	push ecx

	mov ebx, LABEL_IDT ;取IDT表基址

	xor eax, eax
	mov eax, [ebp + 8] ;vectno
	shl eax, 3 ; vectno*8是第vectno号中断描述符在IDT中的偏移位置
	add ebx, eax ; 第vectno号中断描述符在段内的偏移位置

	; 此时, ebx已经指向vectno对应中断的中断描述符了.
	; 下面就可以开始更改此描述符中的内容,即更改中断处理程序。
	; [中断/陷阱门结构]:
	;   %1 - Selector(中断程序所在的段选择子)
	;		%2 - HandlerAddr (驱动程序在段内的地址)
	;		%3 - Attribute (中断属性)
	;
	;	dw %2 & 0ffffh ; 0..15
	;	dw %1
	;	dw (%3 & 0ff00h)
	;	dw (%2 >> 16) & 0ffffh ; 16..31
	xor eax, eax
	xor ecx, ecx
	mov ax, word [ebx] ; 获得处理程序地址的低16位
	mov cx, word [ebx + 6] ; 获得处理程序地址的高16位
	shl ecx, 16
	or  eax, ecx

	pop ecx
	pop ebx

	leave
	ret

;
; <<中断处理程序>>
;

; 默认中断处理
_SpuriousHandler:
SpuriousHandler equ _SpuriousHandler - $$ + 0x30400
;	mov ah, 0ch
;	mov al, '!'
;	mov [gs:(80*0 + 75)*2], ax  ;第0行, 75列
	iretd

; 时钟中断处理(8259A), freq=100Hz
_TimeClockHandler:
TimeClockHandler equ _TimeClockHandler - $$ + 0x30400
	inc		byte [gs:(80*0 + 70)*2]

	mov		al, 20h
	out		20h, al	;发送EOI给主8259片(因为时钟中断是主片产生的,IRQ0).
	iretd

; 内核调度处理
_MyIntHandler:
MyIntHandler equ _MyIntHandler - $$ + 0x30400
	mov ah, 0ch
	mov al, '@'
	mov [gs:(80*0 + 20)*2], ax  ;第0行, 75列
	iretd

⌨️ 快捷键说明

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