linux0.00 masm版

boot.asm

; boot.s is loaded at 7c00h by the bios-startup routines, and moves itself
; out of the way to address 90000h, and jumps there.
;
; It then loads the system at 10000h, using BIOS interrupts. Thereafter
; it disables all interrupts, changes to protected mode, and calls the
; start of system. System then must RE-initialize the protected mode in
; it‘s own tables, and enable interrupts as needed.

.model small
.386p
SEGBIOS SEGMENT AT 8
BIOS    LABEL    BYTE
SEGBIOS ENDS
BOOTSEG SEGMENT    AT 7C0H
    org 5
BOOT    LABEL BYTE
BOOTSEG    ENDS
.code
SYSSEG  equ 1000h            ; system loaded at 10000h (65536).
SYSLEN  equ 17                ; sectors occupied.
start:
    jmp    far ptr BOOT
go:
    mov    ax,cs
    mov    ds,ax
    mov    es,ax
    mov    ss,ax
    mov    sp,400h

; we want to load the system (at 10000h)
load_system:
    mov    dx,0
    mov    cx,2
    mov    ax,SYSSEG
    mov    es,ax
    mov    bx,0
    mov    ax,200h+SYSLEN
    int     13h
    jnc    ok_load
    mov    dx,0
    mov    ax,0
    int    13h
    jmp    load_system

ok_load:

; now we want to move to protected mode ...
    cli            ; no interrupts allowed ;

; then we load the segment descriptors
assume ds:@code

    mov    ax,cs        ; right, forgot this at first. didn‘t work
    mov    ds,ax
    lidt    fword ptr idt_48        ; load idt with 0,0
    lgdt    fword ptr gdt_48        ; load gdt with whatever appropriate

; well, that went ok, I hope. Now we have to reprogram the interrupts
; we put them right after the intel-reserved hardware interrupts, at
; int 20-2F. There they won‘t mess up anything. Sadly IBM really
; messed this up with the original PC, and they haven‘t been able to
; rectify it afterwards. Thus the bios puts interrupts at 08-0f,
; which is used for the internal hardware interrupts as well. We just
; have to reprogram the 8259‘s, and it isn‘t fun.

    mov    al,11h        ; initialization sequence
    out    20h,al        ; send it to 8259A-1
    out    0A0h,al        ; and to 8259A-2
    mov    al,20h        ; start of hardware int‘s (20h)
    out    21h,al
    mov    al,28h        ; start of hardware int‘s 2 (28h)
    out    0A1h,al
    mov    al,04h        ; 8259-1 is master
    out    21h,al
    mov    al,02h        ; 8259-2 is slave
    out    0A1h,al
    mov    al,01h        ; 8086 mode for both
    out    21h,al
    out    0A1h,al
    mov    al,0FFh        ; mask off all interrupts for now
    out    21h,al
    out    0A1h,al

; well, that certainly wasn‘t fun :-(. Hopefully it works, and we don‘t
; need no steenking BIOS anyway (except for the initial loading :-).
; The BIOS-routine wants lots of unnecessary data, and it‘s less
; "interesting" anyway. This is how REAL programmers do it.
;
; Well, now‘s the time to actually move into protected mode. To make
; things as simple as possible, we do no register set-up or anything,
; we let the gnu-compiled 32-bit programs do that. We just jump to
; absolute address 00000, in 32-bit protected mode.

    mov    bx,SYSSEG      ; loaded place.
    mov    ax,0001h    ; protected mode (PE) bit
    lmsw    ax        ; This is it;
    jmp    FAR PTR bios        ; jmp offset 0 of segment 8 (cs)

gdt:
    dw    0,0,0,0        ; dummy

    dw    07FFh        ; 8Mb - limit=2047 (2048*4096=8Mb)
    dw    0000h        ; base address=10000h
    dw    9A01h        ; code read/exec
    dw    00C0h        ; granularity=4096

    dw    07FFh        ; 8Mb - limit=2047 (2048*4096=8Mb)
    dw    0000h        ; base address=10000h
    dw    9201h        ; data read/write
    dw    00C0h        ; granularity=4096

idt_48:
    dw    0        ; idt limit=0
    dw    0,0        ; idt base=0L

gdt_48:
    dw    7ffh        ; gdt limit=2048, 256 GDT entries
    dw    7c00h+gdt,0    ; gdt base = 07xxx

msg1:
    db 13,10
    db "Loading system ..."
    db 13,10,13,10
    org 510
    db 55h,0AAh
end    start

head.asm

;
;  head.s contains the 32-bit startup code.
;  Two L3 task multitasking. The code of tasks are in kernel area,
;  just like the Linux. The kernel code is located at 0x10000.
;
KRN_BASE     = 10000h
TSS0_SEL    = 20h
LDT0_SEL    = 28h
TSS1_SEL    = 30h
LDT1_SEL    = 38h
.386p
.model huge
ts0seg segment at 20h
ts0lab label byte
ts0seg ends
ts1seg segment at 30h
ts1lab label byte
ts1seg ends
.code
startup_32:
    assume ds:@code
    mov eax,10h
    mov ds,eax
    mov es,eax
    mov fs,eax
    mov gs,eax
    lss esp,FWORD PTR [stack_ptr]

; setup base fields of descriptors.
    mov ebx,KRN_BASE
    mov ecx,gdt
    lea eax,tss0
    mov edi,TSS0_SEL
    call set_base
    lea eax,ldt0
    mov edi,LDT0_SEL
    call set_base
    lea eax,tss1
    mov edi,TSS1_SEL
    call set_base
    lea eax,ldt1
    mov edi,LDT1_SEL
    call set_base

    call setup_idt
    call setup_gdt
    mov    eax,10h        ; reload all the segment registers
    mov ds,eax        ; after changing gdt.
    mov es,eax
    mov fs,eax
    mov gs,eax
    lss esp,FWORD PTR [stack_ptr]

;设置8253定时芯片。把计数器通道0设置成每隔10毫秒向中断控制器发送一个中断请求信号
;8253具有3个独立的计数通道,采用减1计数方式。
;方式3为:方波发生器,最适合计算机。
; setup up timer 8253 chip.
    mov al,36h    ;设置通道0工作在方式3
    mov edx,43h     ;8253芯片控制寄存器写端口
    out dx,al
    mov eax,11930        ; timer frequency 100 HZ 8253芯片的时钟输入频率是1.193180mhz
    mov edx,40h        ;通道0的端口
    out dx,al        ;分两次把初始计数值写入通道0
    mov al,ah
    out dx,al

; setup timer & system call interrupt descriptors.
    mov eax,00080000h
    mov ax,1A0h;timer_interrupt
    mov dx,08E00h
    mov ecx,20h
    lea esi,[ecx*8+idt]
    mov [esi],eax
    mov [esi+4],edx
    mov ax,1e4h;[system_interrupt]
    mov dx,0ef00h
    mov ecx,080h
    lea esi,[ecx*8+idt]
    mov [esi],eax
    mov [esi+4],edx

; unmask the timer interrupt.
    mov edx,21h
    in al,dx
    and al,0feh
    out dx,al

; Move to user mode (task 0)
    db 9ch;pushf
    and dword ptr [esp],0ffffbfffh
    db 9dh;popf
    mov eax,TSS0_SEL
    ltr ax
    mov eax,LDT0_SEL
    lldt ax
    mov dword ptr [current],0
    sti
    push 17h
    push stack0_ptr
    db 9ch;pushf
    push 0fh
    push task0
    db 0cfh;iret

setup_gdt:
    lgdt fword ptr [lgdt_opcode]
    ret

setup_idt:
    lea edx,ignore_int
    mov eax,00080000h
    mov ax,dx        ; selector = 0x0008 = cs
    mov dx,8E00h    ; interrupt gate - dpl=0, present
    lea edi,idt
    mov ecx,256
rp_sidt:
    mov [edi],eax
    mov [edi+4],edx
    add edi,8
    dec ecx
    jne rp_sidt
    lidt fword ptr [lidt_opcode]
    ret

; in: eax - logic addr; ebx = base addr ;
; ecx - table addr; edi - descriptors offset.
set_base:
    add    eax,ebx
    add    edi,ecx
    mov    [edi+2],ax
    ror    eax,16
    mov    [edi+4],al
    mov    [edi+7],ah
    ror    eax,16
    ret

write_char:
    push gs
    push ebx
    push eax
    mov ebx,18h
    mov gs,bx
    mov ebx,[scr_loc]
    shl ebx,1
    assume gs:nothing
    mov gs:[ebx],al
    shr ebx,1
    inc ebx
    cmp ebx,2000
    jb f
    mov ebx,0
f:    mov scr_loc,ebx
    pop eax
    pop ebx
    pop gs
    ret

; This is the default interrupt "handler"
    align DWORD
ignore_int:
    push ds
    push eax
    mov eax,10h
    mov ds,eax
    mov eax,67            ; print ‘C‘
    call write_char
    pop eax
    pop ds
    db 0cfh;iret

;Timer interrupt handler
    ;align dword
    dw 0
timer_interrupt:
    push ds
    push edx
    push ecx
    push ebx
    push eax
    mov eax,10h
    mov ds,eax
    mov al,20h
    out 20h,al ;允许其他硬件中断,则向8253发送EOI命令
    mov eax,1
    cmp current,eax
    je ts0
    mov [current],eax
    jmp far ptr ts1lab
    jmp ts2
ts0:    mov dword ptr [current],0 ;若当前任务是1,则把0存入current,并跳转到任务0
    jmp far ptr ts0lab
ts2:    pop eax
    pop ebx
    pop ecx
    pop edx
    pop ds
    db 0cfh;iret

;system call handler
    align DWORD
system_interrupt:
    push ds
    push edx
    push ecx
    push ebx
    push eax
    mov edx,10h
    mov ds,edx
    call write_char
    pop eax
    pop ebx
    pop ecx
    pop edx
    pop ds
    db 0cfh;iret

current    dd 0
scr_loc    dd 0

    align DWORD
    dw 0
lidt_opcode:
    dw 256*8-1        ; idt contains 256 entries
    dd idt + KRN_BASE    ; This will be rewrite by code.
    align DWORD
    dw 0
lgdt_opcode:
    dw (end_gdt-gdt)-1    ; so does gdt
    dd gdt + KRN_BASE    ; This will be rewrite by code.

    align DWORD
    dd 0
idt:
    dd 512 dup(0)        ; idt is uninitialized

gdt:
    dd 00000000h    ; NULL descriptor
    dd 00000000h
    dd 000007ffh    ; 8Mb 0x08, base = 0x10000
    dd 00c09a01h
    dd 000007ffh    ; 8Mb 0x10
    dd 00c09201h
    dd 80000002h    ; screen 0x18 - for display
    dd 00c0920bh

    dd 00000068h    ; TSS0 descr 0x20
    dd 0000e901h
    dd 00000040h    ; LDT0 descr 0x28
    dd 0000e201h
    dd 00000068h    ; TSS1 descr 0x30
    dd 0000e901h
    dd 00000040h    ; LDT1 descr 0x38
    dd 0000e201h
end_gdt:
    dd 128 dup(0)
stack_ptr:
    dd stack_ptr
    dw 10h

    align DWORD
ldt0:
    dd 00000000h
    dd 00000000h
    dd 000003ffh    ; 0x0f, base = 0x10000
    dd 00c0fa01h
    dd 000003ffh    ; 0x17
    dd 00c0f201h
tss0:
    dd 0             ; back link
    dd stack0_krn_ptr,10h    ; esp0, ss0
    dd 0, 0            ; esp1, ss1
    dd 0, 0            ; esp2, ss2
    dd 0            ; cr3
    dd task0        ; eip
    dd 200h            ; eflags
    dd 0, 0, 0, 0        ; eax, ecx, edx, ebx
    dd stack0_ptr,0, 0, 0    ; esp, ebp, esi, edi
    dd 17h,0fh,17h,17h,17h,17h ; es, cs, ss, ds, fs, gs
    dd LDT0_SEL            ; ldt
    dd 8000000h            ; trace bitmap 

    dd 128 dup(0)
stack0_krn_ptr:
    dd 0

    align DWORD
    dd 0
ldt1:
    dd 00000000h
    dd 00000000h
    dd 000003ffh    ; 0x0f, base = 0x10000
    dd 00c0fa01h
    dd 000003ffh    ; 0x17
    dd 00c0f201h
tss1:
    dd 0             ; back link
    dd stack1_krn_ptr, 10h    ; esp0, ss0
    dd 0, 0            ; esp1, ss1
    dd 0, 0            ; esp2, ss2
    dd 0                ; cr3
    dd task1            ; eip
    dd 200h            ; eflags
    dd 0, 0, 0, 0        ; eax, ecx, edx, ebx
    dd stack1_ptr, 0, 0, 0    ; esp, ebp, esi, edi
    dd 17h,0fh,17h,17h,17h,17h ; es, cs, ss, ds, fs, gs
    dd LDT1_SEL            ; ldt
    dd 8000000h            ; trace bitmap 

    dd 128 dup(0)
stack1_krn_ptr:
    dd 0

task0:
    mov eax,17h
    mov ds,ax
    mov eax,65              ; print ‘A‘
    int 80h
    mov ecx,0fffh
s0:    loop s0
    jmp task0 

    dd 128 dup(0)
stack0_ptr:
    dd 0

task1:
    mov eax,17h
    mov ds,ax
    mov eax,66              ; print ‘B‘
    int 80h
    mov ecx,0fffh
s1:    loop s1
    jmp task1

    dd 128 dup(0)
stack1_ptr:
    dd 0
    org 2000h-2
    dw 0
end startup_32

原文地址:https://www.cnblogs.com/lxxhack/p/8415195.html

时间: 2024-10-18 01:07:31

linux0.00 masm版的相关文章

实现多任务的内核Linux0.00分析

最近终于把实现多任务的微内核调试了一遍,我们阐述了如何在保护模式下切换任务.同时知识包括:gdt,idt,ldt,tss,时钟中断服务,特权级切换,显存编程,boot和loader功能,bios调用等等.详细知识还要在实践中摸索学习,希望大家一起进步.这篇文章仅仅做个记录,如没有亲身调试过代码,可能不大好理解.接下几天重点看看0.12启动程序,多分页需要更加深入了解. ;#Mode=Dos ;放在.code前面 .386p .model small LATCH = 11930 SCRN_SEL

[Operating System Labs] 我对Linux0.00中 head.s 的理解和注释

?21,#  head.s contains the 32-bit startup code.#  head.s 是32位的启动代码 #  Two L3 task multitasking. The code of tasks are in kernel area,# 有两个L3(Level 3,即第三特权级,IA32提供给用户0-3,四个特权级,但是Linux0.11只使用了# 0和3这两个特权级,表示用户态程序和内核态程序,内核-kernel)的多任务 #  just like the Li

linux0.00 head.s详细注解

1 # head.s包含32位保护模式初始化设置代码.时钟中断代码.系统调用中断代码和两个任务的代码. 2 # 在初始化完成之后程序移动到任务0开始执行,并在时钟中断控制下进行任务0和1之间的切换操作. 3 LATCH = 11930 # 定时器初始计数值,即每隔10毫秒发送一次中断请求. 问:为何是这个值? 4 SCRN_SEL = 0x18 # 屏幕显示内存段选择符. 问:以下这些选择符是怎么定的值? 5 TSS0_SEL = 0x20 # 任务0的TSS段选择符. 6 LDT0_SEL =

攒机助手专业版6.00 破解版

软件名称:攒机助手专业版 软件版本:6.00软件语言:简体中文软件官网:http://bbs.luobotou.org/thread-3057-1-1.html更新日期:2015.01.23软件破解:Mrack 下载地址:http://pan.baidu.com/s/1m5ccQ 密码: yctf Ps:有能力的请支持下正版. 单机版授权:只能在一台电脑上使用,绑定机器码,10元 无限制授权:可在买家商店.工作室或公司电脑使用,不限数量,20元 正版购买地址: http://item.taoba

002. Linux0.00 head.s注释

http://www.voidcn.com/article/p-newuofyn-hp.html 从网上参考别的详细注释,自己增加了一点点, 用与自己解惑用 .code32 # 多任务内核程序 [32] 位的启动代码 # 包含32位模式下的初始化设置代码,时钟中断代码,系统调用中断代码和两个任务代码 LATCH = 11930 SCRN_SEL=0x18 # 屏幕显示内存段选择符. # 问:以下这些选择符是怎么定的值?根据段选择符的定义:位bit[15-3]为段索引,bit2为0表示GDT,1表

[Operationg System Labs] 我对 Linux0.00 中 boot.s的理解和注释

(如有错误请立即指正,么么哒!) !    boot.s!! It then loads the system at 0x10000, using BIOS interrupts. Thereafter! it disables all interrupts, changes to protected mode, and calls the ! 从0X10000开始,使用BIOS中断加载系统.! 使所有的中断失灵,转入保护模式…… BOOTSEG = 0x07c0             ! b

Linux0.00内核为什么要自己设置0x80号陷阱门来调用write_char过程?

我一开始没注意这个问题,只是通过陷阱门觉得很绕弯子,为何不在3级用户代码里直接调用write_char,今天自己写程序想用call调用代码段,才发现了大问题.我写了类似于write_char的过程,代码如下: dividing_line: push %gs pushl %ebx pushl %ecx movl $1,%ecx/*输出1个空格'  '*/ movl $SCRN_SEL,%ebx movw %bx,%gs 1: movl scr_loc,%ebx shl $1,%ebx movb $

Linux0.00 ld链接时为什么加上-Ttext 0

汇编程序会经过二次遍历,有些符号引用会被标记为可重定位,在编译好后他们的偏移值是其在代码内部的偏移值,即LC计数器的值,当载入内存运行时,由于起始加载地址会不确定,所以会在加载后把代码段所在的内存起始地址加到符号引用原有的偏移上,这就叫重定位.比如一个jmp abc会跳到代码段内部偏移10的地方,但是代码被加载到内存偏移1000,所以实际上那个abc标号偏移10的地方在实际的内存里面偏移是1010,所以再继续往abc(偏移10)跳会出问题,故而给abc的偏移10加上加载处起始地址1000,得出1

硕鼠FLV视频下载软件0.4.7.6去广告绿色版

硕鼠是由著名FLV在线解析网站官方制作的专业FLV下载软件.提供土豆.优酷.我乐.酷六.新浪.搜狐.CCTV等90个主流视频网站的解析+下载+合并/转换一条龙服务.(支持网站不断更新中) 硕鼠支持多线程下载,可智能选择地址,自动命名,FLV/MP4自动合并,智能分类保存,特色的“一键”下载整个专辑的功能,无需人工干预,并集成了转换工具可将下载文件批量转换为3gp,AVI,MP4等格式. 特点 专业的解析引擎,强大的批量下载能力,全面的后期处理工具.,绿色轻盈小巧,无插件,无恶意代码 00.绿色版