linux0.00 masm版

Posted lxxhack

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

 

以上是关于linux0.00 masm版的主要内容,如果未能解决你的问题,请参考以下文章

包含 MASM 的文件

[vscode]--HTML代码片段(基础版,reactvuejquery)

求一个汇编语言课程设计的MASM32时钟的程序

使用 masm 将简单字符串写入控制台(汇编代码)

为啥我的 C 代码片段不起作用?简化版可以。为 unsigned long long 传递不带 VA_ARGS 的 args

汇编学习环境搭建