Linux 0.00

From Computer History Wiki
Jump to: navigation, search


Linux 0.00
Linux 0.00 on Qemu.jpg
Linux 0.00 doing what id does best
Type: Multitasking
Creator: Linus Torvalds
Architecture: IBM 386
Current Version: 2.6 (2010)
Year Introduced: 1991
Linux 0.00 was the first version that simply went into protected mode, started two tasks, and switched between the two printing "AAAA" & "BBBB".
"it switched between two processes that printed AAAA...  and BBBB...
respectively by using the timer-interrupt - Gods I was proud over that"


                                                    --Linus Torvalds

Getting this to run

So far the only place I've found with a binary is over at oldlinux.org. I was able to convert the boot image into something that Qemu understands and was able to run. Otherwise, it ought to run with an older version of Bochs.

You can download the floppy disk image here

Commented Source Code

Linux as this point only comprised two files. The following was taken from this forum post.

# Boot.s this code has been transferred to the memory 0 x10000, and in protected mode 
KRN_BASE = 0x10000 
# Boot.s we have learned about the structure of the Register, which is the index table at the gdt 
# Gdt a table of the table of eight bytes. Each user process of the two gdt table, and ldt tss 
Not # 1 
# The second is the code of the system 
# The third is the system of data 
# 3 is the memory of the system 

TSS0_SEL = 0x20 
LDT0_SEL = 0x28 
TSS1_SEL = 0X30 
LDT1_SEL = 0x38 

. Text 
Startup_32: 
# Register all of the data, all point system, gdt Table 3 
    Movl $ 0x10,% eax 
    Mov% ax,% ds 
    Mov% ax,% es 
    Mov% ax,% fs 
    Mov% ax,% gs 
# Load the stack of address 
    Lss stack_ptr,% esp 

# 
# Linux-0.00 There are two processes, one has been Print A, B another has been Print 
# Switching until 8253 have interrupted the process 
# Operating system paging mechanism used by the former sub mechanism. In modern operating systems, 
# Some say cleverly around Linux in the past, some people say that is not ... 
# 
# Mechanism for the use of sub-systems for each user process the two gdt table, a paragraph is tss, another paragraph is ldt 
# The following two dozen lines of code set up the process of tss, and ldt 
These two paragraphs # absolute addresses wrote gdt table of the corresponding local 
Gdt Table # Please refer to the structure of the C Program 
# Http://blog.chinaunix.net/u/23177/showart_209429.html 
# 

    Movl $ KRN_BASE,% ebx 
    Movl $ gdt,% ecx 
    Lea tss0,% eax 
    Movl $ TSS0_SEL,% edi 
    Call set_base 
    Lea ldt0,% eax 
    Movl $ LDT0_SEL,% edi 
    Call set_base 
    Lea tss1,% eax 
    Movl $ TSS1_SEL,% edi 
    Call set_base 
    Lea ldt1,% eax 
    Movl $ LDT1_SEL,% edi 
    Call set_base 

# Setup_idt to 256 interrupt vector processing functions are set to ignore_int 
    Call setup_idt 
# Global descriptor table and the length of the initial address printed in the Register gdtr 
    Call setup_gdt 
    Movl $ 0x10,% eax # reload all the segment registers 
    Mov% ax,% ds # after changing gdt. 
    Mov% ax,% es 
    Mov% ax,% fs 
    Mov% ax,% gs 
    Lss stack_ptr,% esp 

# Setup up timer 8253 chip. 
    Movb $ 0x36,% al 
    Movl $ 0x43,% edx 
    Outb% al,% dx 
    Movl $ 11,930,% eax # timer frequency 100 HZ 
    Movl $ 0x40,% edx 
    Outb% al,% dx 
    Movb% ah,% al 
    Outb% al,% dx 

# 
# There are three operating systems interruption, software interruption, and processor hardware interrupt abnormal 
# Timer_interrupt hardware interrupt handling procedures, the film tells the system time, the switching process 
# System_interrupt interrupt processing software, users can use the system to process called Print the letters A or B 
# 
# Mode is the IDT (interrupt descriptor table) in the memory address 0 x0 started from the local 
# Protected mode register idtr have a special place at the beginning of IDT 
IDT # therefore need not address 0 x0 started on the place 
# Mode is a disruption to account for 4 bytes, 256 1 k byte 
A # protected mode interrupt descriptor or 8 bytes; 256 total 2k bytes 
# 
# Protected mode interrupt descriptor is interrupted doors, trap doors or doors task. Some said there is a book called Gate 
# Interrupted doors and trap doors only difference is not allowed to interrupt the door further interruption, that is the meaning of the Executive interrupted doors 
# Interrupt handling procedures at customs is interrupted. The door to the hardware interrupt handling interruption 
# Trap door opposite, allowing interruption processing software interruption. The code below shows this point 
Door # task switching process provides a hardware-level support. Now the Linux kernel and not the use of this mechanism 

# However linux-0.00 indeed use this hardware switching mechanism 
# 

# Interrupt handling procedures set up where the paragraph is the system code, the table is the second gdt 
# Interrupt handling procedures and paragraph migration in the high 16 location 0 
    Movl $ 0x00080000,% eax 
# Interrupt handling procedures set up in the migration of the low 16 
    Movw $ timer_interrupt,% ax 
# Core states interrupted doors, and the doors effective 
    Movw $ 0x8E00,% dx 
# Timer_interrupt interrupt vector is 32, 
    Movl $ 0x20,% ecx 
    Lea idt (,% ecx, 8),% esi 
# Will be set up on the door interrupted the good content wrote idt corresponding table (32) 
    Movl% eax, (% esi) 
    Movl% edx, 4 (% esi) 

# Interrupt handling procedures set up in the migration of the low 16 
    Movw $ system_interrupt,% ax 
# User-trap doors, and the doors effective 
    Movw $ 0xef00,% dx 
# System_interrupt interrupt vector is 128, 
    Movl $ 0x80,% ecx 
    Lea idt (,% ecx, 8),% esi 
# Trap door will be erected good idt wrote the contents of the corresponding table (128) 
    Movl% eax, (% esi) 
    Movl% edx, 4 (% esi) 

# Unmask the timer interrupt. 
    Movl $ 0x21,% edx 
    Inb% dx,% al 
    Andb $ 0xfe,% al 
    Outb% al,% dx 

# 
# The following three lines of code set up EFLAGS NT 0 
# NT = 0 to the following tasks to prepare for switch 
# "Linux kernel completely Notes" section 102 403 lines of code as follows (kernel / sched.c): 
# __asm__ ( "Pushfl; andl $ 0xffffbfff, (% esp); popfl"); 
# The following three lines of code above is launched 
# 
# NT nested task is the acronym EFLAGS of the first 15 signs. When NT = 0:00 no task switching 
# Behind tss0 and tss1 structure in eflags = 0x0200, which is NT = 1, a task switching 
# 
# X86 a total of four ways switching tasks 
# 1. Ljmp $ task_selector, $ 0 
# 2. Lcall $ task_selector, $ 0 
# 3. Int 0x80 
# 4. Iret 
# Ljmp and lcall distinction is no longer Jump ljmp not come back, but can also Jump back lcall 
# Int 0x80 must Jump to the mission doors 
# NT iret must be set to 1 
# Behind the timer interrupt handling functions is used ljmp timer_interrupt 
# Ljmp $ TSS0_SEL, $ 0 
# Ljmp $ TSS1_SEL, $ 0 
# 
    Pushfl 
    Andl $ 0xffffbfff, (% esp) 
    Popfl 

# Printed in the process 0 task Register 
    Movl $ TSS0_SEL,% eax 
    Ltr% ax 
# Printed in the process 0 local descriptor table register 
    Movl $ LDT0_SEL,% eax 
    Lldt% ax 
# Set up the current process was 0 
    Movl $ 0, current 
# Open interruption. Iret after two tasks can be run alternately 
    Sti 
    Pushl $ 0x17 
    Pushl $ stack0_ptr 
    Pushfl 
    Pushl $ 0x0f 
    Pushl $ task0 
# No task switching (NT = 0), only Jump to task0 punishable by implementing user - 
# I think that also can be understood as Jump to a special task 0 process 
    Iret 

/****************************************/ 
Setup_gdt: 
    Lgdt lgdt_opcode 
    Ret 

Setup_idt: 
    Lea ignore_int,% edx 
    Movl $ 0x00080000,% eax 
    Movw% dx,% ax / * selector = 0x0008 = cs * / 
    Movw $ 0x8E00,% dx / * interrupt gate - dpl = 0, present * / 
    Lea idt,% edi 
    Mov $ 256,% ecx 
Rp_sidt: 
    Movl% eax, (% edi) 
    Movl% edx, 4 (% edi) 
    Addl $ 8,% edi 
    Dec% ecx 
    Jne rp_sidt 
    Lidt lidt_opcode 
    Ret 

# In:% eax - logic addr;% ebx = base addr; 
#% Ecx - table addr;% edi - descriptors offset. 
Set_base: 
    Addl% ebx,% eax 
    Addl% ecx,% edi 
    Movw% ax, 2 (% edi) 
    Rorl $ 16,% eax 
    Movb% al, 4 (% edi) 
    Movb% ah, 7 (% edi) 
    Rorl $ 16,% eax 
    Ret 

Write_char: 
    Push% gs 
    Pushl% ebx 
    Pushl% eax 
# Printed in the memory of 
    Mov $ 0x18,% ebx 
    Mov% bx,% gs 
# Shown by the last character position 
    Movl scr_loc,% bx 
# Each of the two-byte characters, the first byte is what we have to show that the byte 
    Shl $ 1,% ebx 
# Characters' A 'or' B 'direct wrote in memory 
    Movb% al,% gs: (% ebx) 
# Of a two-byte characters, the second byte is the attribute byte 
# For example 0 x07 is normal, black white; 0 x70 is reversed - phase, black white 
# When the procedures set up a property, it would maintain the same attribute, after all the characters have the same attributes 
# Until another operation changed the attributes 
# If add the following three lines here, it will be the effect of white black 
# Inc% ebx 
# Movb $ 0x70,% gs: (% ebx) 
# Dec% ebx 
    Shr $ 1,% ebx 
    Incl% ebx 
# CGA provides both texts model 40 x25 and 80 x25, if it is 80 x25 that is a screen can have 2,000 characters 
# Characters each pixel of 8x8 months, the CGA has two resolution 320 x 200 and 640 x 200 
# If the following 2000 to 1000, we will find that only a former semi-screen output 
    Cmpl $ 2000,% ebx 
# If visitors fill a screen, then start again 
    Jb 1f 
# Counter Fu 0 
    Movl $ 0,% ebx 
# Preserve the current cursor position 
1: movl% ebx, scr_loc 
    Popl% eax 
    Popl% ebx 
    Pop% gs 
    Ret 

/***********************************************/ 
/ * This is the default interrupt "handler" :-) * / 
. Align 2 
Ignore_int: 
    Push% ds 
    Pushl% eax 
    Movl $ 0x10,% eax 
    Mov% ax,% ds 
    Movl $ 67,% eax / * print 'C' * / 
    Call write_char 
    Popl% eax 
    Pop% ds 
    Iret 

/ * Timer interrupt handler * / 
. Align 2 
Timer_interrupt: 
    Push% ds 
    Pushl% edx 
    Pushl% ecx 
    Pushl% ebx 
    Pushl% eax 
    Movl $ 0x10,% eax 
    Mov% ax,% ds 
    Movb $ 0x20,% al 
    Outb% al, $ 0x20 
    Movl $ 1,% eax 
    Cmpl% eax, current 
    Je 1f 
    Movl% eax, current 
    Ljmp $ TSS1_SEL, $ 0 
    Jmp 2f 
1: movl $ 0, current 
    Ljmp $ TSS0_SEL, $ 0 
2: popl% eax 
    Popl% ebx 
    Popl% ecx 
    Popl% edx 
    Pop% ds 
    Iret 

/ * System call handler * / 
. Align 2 
System_interrupt: 
    Push% ds 
    Pushl% edx 
    Pushl% ecx 
    Pushl% ebx 
    Pushl% eax 
    Movl $ 0x10,% edx 
    Mov% dx,% ds 
    Call write_char 
    Popl% eax 
    Popl% ebx 
    Popl% ecx 
    Popl% edx 
    Pop% ds 
    Iret 

/*********************************************/ 
Current:. Long 0 
Scr_loc:. Long 0 

. Align 2 
. Word 0 
Lidt_opcode: 
    . Word 256 * 8-1 # idt contains 256 entries 
    . Long idt + KRN_BASE # This will be rewrite by code. 
. Align 2 
. Word 0 
Lgdt_opcode: 
    . Word (end_gdt - gdt) -1 # so does gdt 
    . Long gdt + KRN_BASE # This will be rewrite by code. 

    . Align 3 
Idt:. Fill 256,8,0 # idt is uninitialized 

Gdt:. Quad 0x0000000000000000 / * NULL descriptor * / 
    . Quad 0x00c09a01000007ff / * 8Mb 0x08, base = 0x10000 * / 
    . Quad 0x00c09201000007ff / * 8Mb 0x10 * / 

# Control段描述符table can know the definition of the base site is 0 xb8000 (736K) 
# "Linux kernel completely Notes," a book 206 649 lines of code as follows 
# Vidio_mem_start = 0xb8000 
# Note the color mode shows the initial memory address is 0 xb8000 
    . Quad 0x00c0920b80000002 / * screen 0x18 - for display * / 

    . Quad 0x0000e90100000068 # TSS0 descr 0x20 
    . Quad 0x0000e20100000040 # LDT0 descr 0x28 
    . Quad 0x0000e90100000068 # TSS1 descr 0x30 
    . Quad 0x0000e20100000040 # LDT1 descr 0x38 
End_gdt: 
    . Fill 128,4,0 
Stack_ptr: 
    . Long stack_ptr 
    . Word 0x10 

/*************************************/ 
. Align 3 
Ldt0:. Quad 0x0000000000000000 
    . Quad 0x00c0fa01000003ff # 0x0f, base = 0x10000 
    . Quad 0x00c0f201000003ff # 0x17 
Tss0: 
    . Long 0 / * back link * / 
    . Long stack0_krn_ptr, 0x10 / * esp0, ss0 * / 
    . Long 0, 0 / * esp1, ss1 * / 
    . Long 0, 0 / * esp2, ss2 * / 
    . Long 0 / * cr3 * / 
    . Long task0 / * eip * / 
    . Long 0x200 / * eflags * / 
    . Long 0, 0, 0, 0 / * eax, ecx, edx, ebx * / 
    . Long stack0_ptr, 0, 0, 0 / * esp, ebp, esi, edi * / 
    . Long 0x17, 0x0f, 0x17, 0x17, 0x17, 0x17 / * es, cs, ss and ds, fs, gs * / 
    . Long LDT0_SEL / * ldt * / 
    . Long 0x8000000 / * trace bitmap * / 

    . Fill 128,4,0 
Stack0_krn_ptr: 
    . Long 0 

/************************************/ 
. Align 3 
Ldt1:. Quad 0x0000000000000000 
    . Quad 0x00c0fa01000003ff # 0x0f, base = 0x10000 
    . Quad 0x00c0f201000003ff # 0x17 
Tss1: 
    . Long 0 / * back link * / 
    . Long stack1_krn_ptr, 0x10 / * esp0, ss0 * / 
    . Long 0, 0 / * esp1, ss1 * / 
    . Long 0, 0 / * esp2, ss2 * / 
    . Long 0 / * cr3 * / 
    . Long task1 / * eip * / 
    . Long 0x200 / * eflags * / 
    . Long 0, 0, 0, 0 / * eax, ecx, edx, ebx * / 
    . Long stack1_ptr, 0, 0, 0 / * esp, ebp, esi, edi * / 
    . Long 0x17, 0x0f, 0x17, 0x17, 0x17, 0x17 / * es, cs, ss and ds, fs, gs * / 
    . Long LDT1_SEL / * ldt * / 
    . Long 0x8000000 / * trace bitmap * / 

    . Fill 128,4,0 
Stack1_krn_ptr: 
    . Long 0 

/************************************/ 
Task0: 
    Movl $ 0x17,% eax 
    Movw% ax,% ds 
    Movl $ 65,% al / * print 'A' * / 
    Int $ 0x80 
    Movl $ 0xfff,% ecx 
1: loop 1b 
    Jmp task0 

    . Fill 128,4,0 
Stack0_ptr: 
    . Long 0 

Task1: 
    Movl $ 0x17,% eax 
    Movw% ax,% ds 
    Movl $ 66,% al / * print 'B' * / 
    Int $ 0x80 
    Movl $ 0xfff,% ecx 
1: loop 1b 
    Jmp task1 

    . Fill 128,4,0 
Stack1_ptr: 
    . Long 0 

/ *** *** End /