mbr.asm
;=============================================================================== ;FileName: mbr.asm ;Complie Method: nasm mbr.asm -o mbr.bin ;Descriptor: MBR ;Author: by Taozai ;Date: 2015/01/16 ;=============================================================================== core_base_address equ 0x00040000 core_start_sector equ 0x00000001 ;set stack. mov ax,cs mov ss,ax mov sp,0x7c00 ;calc GDT segment address. mov eax,[cs:pgdt+0x7c00+0x02] xor edx,edx mov ebx,16 div ebx mov ds,eax ;GDT segment address. mov ebx,edx ;GDT offset address. ;#0 default to set 0. mov dword [ebx+0x00],0x00000000 mov dword [ebx+0x04],0x00000000 ;#1 data segment. mov dword [ebx+0x08],0x0000ffff ;base address is 0x00000000, segment bound is 0xfffff mov dword [ebx+0x0c],0x00cf9200 ;Granularity is 4KB. ;bits[0000 0000 _1_1_0_0 _1111 _1_00_1 _0010 _0000 0000] ;#2 init code. mov dword [ebx+0x10],0x7c0001ff ;base address is 0x00007c00, segment bound is 0x001ff mov dword [ebx+0x14],0x00409800 ;Granularity is 1 bit. ;bits[0000 0000 _0_1_0_0 _0000 _1_00_1 _1000 _0000 0000] ;#3 stack segment mov dword [ebx+0x18],0x7c00fffe ;base address is 0x00007c00, segment bound is 0xffffe mov dword [ebx+0x1c],0x00cf9600 ;Granularity is 4KB. ;bits[0000 0000 _1_1_0_0 _1111 _1_00_1 _0110 _0000 0000] ;#4 According to the buffer. mov dword [ebx+0x20],0x80007fff ;base address is 0x000B8000, segment bound is 0x07fff mov dword [ebx+0x24],0x0040920b ;Granularity is 1 bit. ;bits[0000 0000 _0_1_0_0 _0000 _1_00_1 _0010 _0000 1011] ;set gdt bound. mov word [cs:pgdt+0x7c00],39 ;load gdt. lgdt [cs:pgdt+0x7c00] ;Preparation for entry into the protected mode. in al,0x92 or al,0000_0010B out 0x92,al ;disable interrupt. cli ;set PE mov eax,cr0 or eax,1 mov cr0,eax ;Enter the protected mode. jmp dword 0x0010:flush ;bits[0000 0000 0001 0_0_00] [bits 32] flush: mov eax,0x0008 ;bits[0000 0000 0000 1_0_00] mov ds,eax mov eax,0x0018 ;bits[0000 0000 0001 1_0_00] mov ss,eax xor esp,esp ;load core program. mov edi,core_base_address mov eax,core_start_sector mov ebx,edi call read_hard_disk_0 ;calc core program size. mov eax,[edi] xor edx,edx mov ecx,512 div ecx or edx,edx jnz @1 dec eax @1: or eax,eax jz setup mov ecx,eax mov eax,core_start_sector inc eax @2: call read_hard_disk_0 inc eax loop @2 setup: mov esi,[0x7c00+pgdt+0x02] ;#5 sys routine seg. mov eax,[edi+0x04] mov ebx,[edi+0x08] sub ebx,eax dec ebx ;seg bound. add eax,edi ;base address. mov ecx,0x00409800 ;bits[0000 0000 _0_1_0_0 _0000 _1_00_1 _1000 _000 0000] call make_gdt_descriptor mov [esi+0x28],eax mov [esi+0x2c],edx ;#6 core data seg. mov eax,[edi+0x08] mov ebx,[edi+0x0c] sub ebx,eax dec ebx add eax,edi mov ecx,0x00409200 ;bits[0000 0000 _0_1_0_0 _0000 _1_00_1 _0010 _0000 0000] call make_gdt_descriptor mov [esi+0x30],eax mov [esi+0x34],edx ;#7 core code seg. mov eax,[edi+0x0c] mov ebx,[edi+0x00] sub ebx,eax dec ebx add eax,edi mov ecx,0x00409800 ;bits[0000 0000 _0_1_0_0 _0000 _1_00_1 _1000 _000 0000] call make_gdt_descriptor mov [esi+0x38],eax mov [esi+0x3c],edx mov word [0x7c00+pgdt],63 lgdt [0x7c00+pgdt] jmp far [edi+0x10] ;------------------------------------------------------------------- ; read 1 sector ; params: ; EAX= src sector id. ; DS:EBX=dst address. ; ;return: ; EBX=EBX+512 ; read_hard_disk_0: push eax push ecx push edx push eax mov dx,0x1f2 mov al,1 out dx,al ;read sector count. inc dx ;0x1f3 pop eax out dx,al ;LBA(7~0) inc dx ;0x1f4 mov cl,8 shr eax,cl out dx,al ;LBA(15~8) inc dx ;0x1f5 shr eax,cl out dx,al ;LBA(23~16) inc dx ;0x1f6 shr eax,cl or eax,0xe0 ;1 hard disk. LBA(27~24) out dx,al inc dx ;0x1f7 mov al,0x20 ;read command. out dx,al .waits: in al,dx and al,0x88 cmp al,0x08 jnz .waits mov ecx,256 mov dx,0x1f0 .readw: in ax,dx mov [ebx],ax add ebx,2 loop .readw pop edx pop ecx pop eax ret ;------------------------------------------------------------------- ; buil gdt item. ; params: ; EAX= base address. ; EBX= segment bound. ; ECX= properties. ; ;return: ; EDX:EAX=gdt item. ; make_gdt_descriptor: mov edx,eax shl eax,16 or ax,bx and edx,0xffff0000 rol edx,8 bswap edx xor bx,bx or edx,ebx or edx,ecx ret ;------------------------------------------------------------------- pgdt dw 0 ;bound. dd 0x0007e00 ;GDT address. ;------------------------------------------------------------------- times 510-($-$$) db 0 db 0x55,0xaa
core.asm
;=============================================================================== ;FileName: core.asm ;Complie Method: nasm core.asm -o core.bin ;Descriptor: CORE ;Author: by Taozai ;Date: 2015/02/03 ;=============================================================================== ; ;defines ; core_code_seg_sel equ 0x38 ;core code segment selector. ;bits[0000 0000 0011 1_0_00] #7 core_data_seg_sel equ 0x30 ;core data segment selector. ;bits[0000 0000 0011 0_0_00] #6 sys_routine_seg_sel equ 0x28 ;system routine segment selector. ;bits[0000 0000 0010 1_0_00] #5 video_ram_seg_sel equ 0x20 ;video ram segment selector. ;bits[0000 0000 0010 0_0_00] #4 core_stack_seg_sel equ 0x18 ;core stack segment selector. ;bits[0000 0000 0001 1_0_00] #3 mem_0_4_gb_seg_sel equ 0x08 ;(0~4GB) segment selector. ;bits[0000 0000 0000 1_0_00] #1 ;------------------------------------------------------------------------------- ; ;core header. ; core_length dd core_end ;#00 the total length of core program. sys_routine_seg dd section.sys_routine.start ;#04 system utility routines section position. core_data_seg dd section.core_data.start ;#08 the position of the core data. core_code_seg dd section.core_code.start ;#0c the position of the core code. code_entry dd start ;#10 the core code entry point. dw core_code_seg_sel [bits 32] ;=============================================================================== SECTION sys_routine vstart=0 ;------------------------------------------------------------------------------- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; public: ; print string. ; ; parameters: ; DS:EBX = string address. ; ; return: ; put_string: push ecx .getc: mov cl,[ebx] or cl,cl jz .exit call put_char inc ebx jmp .getc .exit: pop ecx retf ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; private: ; print char. ; ; parameters: ; CL = ANSCII. ; ; return: ; put_char: ;pusha: push ax,cx,dx,bx,sp,bp,si,di 16bits. pushad ;pushad: push eax,ecx,edx,ebx,esp,ebp,esi,edi 32bits. mov dx,0x3d4 mov al,0x0e out dx,al inc dx in al,dx mov ah,al dec dx mov al,0x0f out dx,al inc dx in al,dx mov bx,ax ;BX=cursor position. cmp cl,0x0d ;enter? jnz .put_0a mov ax,bx mov bl,80 div bl mul bl ;ax=al*bl mov bx,ax jmp .set_cursor .put_0a: cmp cl,0x0a ;newline. jnz .put_other add bx,80 jmp .roll_screen .put_other: push es mov eax,video_ram_seg_sel mov es,eax shl bx,1 ;BX=BX*2 mov [es:bx],cl pop es shr bx,1 inc bx .roll_screen: cmp bx,2000 jl .set_cursor ;< push ds push es mov eax,video_ram_seg_sel mov ds,eax mov es,eax cld ;CLear Direction flag. esi++, edi++ mov esi,0xa0 mov edi,0x00 mov ecx,1920 rep movsd mov bx,3840 mov ecx,80 .cls: mov word[es:bx],0x0720 add bx,2 loop .cls pop es pop ds mov bx,1920 .set_cursor: mov dx,0x3d4 mov al,0x0e out dx,al ;0x3d4 inc dx mov al,bh out dx,al ;0x3d5 dec dx mov al,0x0f out dx,al ;0x3d4 inc dx mov al,bl out dx,al ;0x3d5 popad ret ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; public: ; a logical sector read from the hard disk. ; ; parameters: ; EAX = logical sector number. ; DS:EBX = target buffer address. ; ; return: ; EBX = EBX+512 ; read_hard_disk_0: push eax push ecx push edx push eax mov dx,0x1f2 mov al,1 ;read sector count. out dx,al inc dx ;0x1f3 pop eax out dx,al ;LBA(7~0) inc dx ;0x1f4 mov cl,8 shr eax,cl out dx,al ;LBA(15~8) inc dx ;0x1f5 shr eax,cl out dx,al ;LBA(23~16) inc dx ;0x1f6 shr eax,cl or al,0xe0 ;0 hard disk, LBA(27~24) out dx,al inc dx ;0x1f7 mov al,0x20 out dx,al ;read command. .waits: in al,dx and al,0x88 cmp al,0x08 jnz .waits mov ecx,256 mov dx,0x1f0 .readw: in ax,dx mov [ebx],ax add ebx,2 loop .readw pop edx pop ecx pop eax retf ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; public: ; In the current cursor displayed in hexadecimal. ; ; parameters: ; EDX = To transform and digital display. ; ; return: ; put_hex_dword: pushad push ds mov ax,core_data_seg_sel mov ds,ax mov ebx,bin_hex ;First address TABLE for a written form. mov ecx,8 ;8 bytes. .xlt: rol edx,4 mov eax,edx and eax,0x0000000f xlat push ecx mov cl,al ;ANSCII. call put_char pop ecx loop .xlt pop ds popad retf ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; public: ; Allocate memory. ; ; parameters: ; ECX = Distribution of the number of bytes of memory. ; ; return: ; ECX = The start of the allocated memory linear addresses. ; allocate_memory: push ds push eax push ebx mov eax,core_data_seg_sel mov ds,eax mov eax,[ram_alloc] add eax,ecx ;The next time the starting address of the allocated memory. mov ecx,[ram_alloc] ;Return to the starting address of the allocated memory. mov ebx,eax and ebx,0xfffffffc ;4 byte alignment. add ebx,4 test eax,0x00000003 cmovnz eax,ebx mov [ram_alloc],eax pop ebx pop eax pop ds retf ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ;public: ; Install a new descriptor in the GDT. ; ; params: ; EDX:EAX = The descriptor. ; ;return: ; CX = The choice of the descriptor. ; set_up_gdt_descriptor: push eax push ebx push edx push ds push es mov ebx,core_data_seg_sel mov ds,ebx sgdt [pgdt] ;Save the global descriptor. mov ebx,mem_0_4_gb_seg_sel mov es,ebx movzx ebx,word [pgdt] ;GDT boundaries. inc bx ;GDT total number of bytes, is also a descriptor under deviation. add ebx,[pgdt+2] ;Under a descriptor linear address. mov [es:ebx],eax ;Under a descriptor linear address. mov [es:ebx+4],edx add word [pgdt],8 ;Increase the size of a descriptor. lgdt [pgdt] ;The GDT changes to take effect. mov ax,[pgdt] ;Get the GDT threshold value. xor dx,dx mov bx,8 div bx ;Divided by the number 8, remove the remainder. mov cx,ax shl cx,3 ;Index number will be moved to the right place. pop es pop ds pop edx pop ebx pop eax retf ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ;public: ; To construct storage and segment descriptor systems. ; ; params: ; EAX = base address. ; EBX = segment bound. ; ECX = properties. ; ;return: ; EDX:EAX = gdt item. ; make_seg_descriptor: mov edx,eax shl eax,16 or ax,bx and edx,0xffff0000 rol edx,8 bswap edx ;(80486+) xor bx,bx or edx,ebx or edx,ecx retf ;=============================================================================== SECTION core_data vstart=0 ;------------------------------------------------------------------------------- pgdt dw 0 dd 0 ram_alloc dd 0x00100000 salt: salt_1 db '@PrintString' times 256-($-salt_1) db 0 dd put_string dw sys_routine_seg_sel salt_2 db '@ReadDiskData' times 256-($-salt_2) db 0 dd read_hard_disk_0 dw sys_routine_seg_sel salt_3 db '@PrintDwordAsHexString' times 256-($-salt_3) db 0 dd put_hex_dword dw sys_routine_seg_sel salt_4 db '@TerminateProgram' times 256-($-salt_4) db 0 dd return_point dw core_code_seg_sel ;defines. salt_item_len equ $-salt_4 salt_items equ ($-salt)/salt_item_len message_1 db ' If you seen this message,that means we ' db 'are now in protect mode,and the system ' db 'core is loaded,and the video display ' db 'routine works perfectly.',0x0d,0x0a,0 message_5 db ' Loading user program...',0 do_status db 'Done.',0x0d,0x0a,0 message_6 db 0x0d,0x0a,0x0d,0x0a,0x0d,0x0a db ' User program terminated,control returned.',0 bin_hex db '0123456789ABCDEF' core_buf times 2048 db 0 esp_pointer dd 0 cpu_brnd0 db 0x0d,0x0a,' ',0 cpu_brand times 52 db 0 cpu_brnd1 db 0x0d,0x0a,0x0d,0x0a,0 ;=============================================================================== SECTION core_code vstart=0 ;------------------------------------------------------------------------------- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; private: ; loading and positioning the user program. ; ; parameters: ; ESI = starting logical sector number. ; ; return: ; AX = point to the user program head selector. ; load_relocate_program: push ebx push ecx push edx push esi push edi push ds push es mov eax,core_data_seg_sel mov ds,eax mov eax,esi mov ebx,core_buf call sys_routine_seg_sel:read_hard_disk_0 mov eax,[core_buf] mov ebx,eax and ebx,0xfffffe00 ;512 byte alignment. add ebx,512 test eax,0x000001ff cmovnz eax,ebx mov ecx,eax call sys_routine_seg_sel:allocate_memory mov ebx,ecx push ebx xor edx,edx mov ecx,512 div ecx mov ecx,eax ;sector count. mov eax,mem_0_4_gb_seg_sel mov ds,eax mov eax,esi ;Start sector number. .b1: call sys_routine_seg_sel:read_hard_disk_0 inc eax loop .b1 ;Loop reads the user program. ;#? head seg. pop edi ;push ebx, The user program first address. mov eax,edi ;The head start program linear address. mov ebx,[edi+0x04] ;length. dec ebx ;segment boundaries. mov ecx,0x00409200 ;bits[00000 0000 _0_1_0_0 _0000 _1_00_1 _0010 _0000 0000] call sys_routine_seg_sel:make_seg_descriptor call sys_routine_seg_sel:set_up_gdt_descriptor mov [edi+0x04],cx ;#?+1 code seg. mov eax,edi add eax,[edi+0x14] ;Initial linear address code mov ebx,[edi+0x18] ;length. dec ebx ;segment boundaries. mov ecx,0x00409800 ;bits[0000 0000 _0_1_0_0 _0000 _100_1 _1000 _0000 0000] call sys_routine_seg_sel:make_seg_descriptor call sys_routine_seg_sel:set_up_gdt_descriptor mov [edi+0x14],cx ;#?+2 data seg. mov eax,edi add eax,[edi+0x1c] ;Initial linear address code mov ebx,[edi+0x20] ;length. dec ebx ;segment boundaries. mov ecx,0x00409200 ;bits[0000 0000 _0_1_0_0 _0000 _100_1 _0010 _0000 0000] call sys_routine_seg_sel:make_seg_descriptor call sys_routine_seg_sel:set_up_gdt_descriptor mov [edi+0x1c],cx ;#?+3 stack seg. mov ecx,[edi+0x0c] ;Ratio of 4 KB. mov ebx,0x000fffff sub ebx,ecx ;Get segment boundaries. mov eax,4096 mul dword [edi+0x0c] mov ecx,eax call sys_routine_seg_sel:allocate_memory add eax,ecx ;Get a stack of high-end physical address. mov ecx,0x00c09600 ;bits[0000 0000 _1_1_0_0 _0000 _100_1 _0110 _0000 0000] call sys_routine_seg_sel:make_seg_descriptor call sys_routine_seg_sel:set_up_gdt_descriptor mov [edi+0x08],cx mov eax,[edi+0x04] mov es,eax mov eax,core_data_seg_sel mov ds,eax cld ;cld; DF=0 (esi++, edi++) mov ecx,[es:0x24] ;The user program SALT number entries. mov edi,0x28 ;The SALT in the user program is 0 x28 place inside the head. .b2: push ecx push edi mov ecx,salt_items mov esi,salt .b3 push edi push esi push ecx mov ecx,64 ; repe cmpsd jnz .b4 mov eax,[esi] mov [es:edi-256],eax mov ax,[esi+4] mov [es:edi-252],ax .b4: pop ecx pop esi add esi,salt_item_len pop edi loop .b3 ;end .b3 pop edi add edi,256 pop ecx loop .b2 ;end .b2 mov ax,[es:0x04] ;Returns the user program head index number. pop es pop ds pop edi pop esi pop edx pop ecx pop ebx ret ;------------------------------------------------------------------------------- ; ;the core code entry point. ; start: mov ecx,core_data_seg_sel mov ds,ecx mov ebx,message_1 call sys_routine_seg_sel:put_string ;show . mov eax,0x80000002 cpuid mov [cpu_brand + 0x00],eax mov [cpu_brand + 0x04],ebx mov [cpu_brand + 0x08],ecx mov [cpu_brand + 0x0c],edx mov eax,0x80000003 cpuid mov [cpu_brand + 0x10],eax mov [cpu_brand + 0x14],ebx mov [cpu_brand + 0x18],ecx mov [cpu_brand + 0x1c],edx mov eax,0x80000004 cpuid mov [cpu_brand + 0x20],eax mov [cpu_brand + 0x24],ebx mov [cpu_brand + 0x28],ecx mov [cpu_brand + 0x2c],edx mov ebx,cpu_brnd0 call sys_routine_seg_sel:put_string mov ebx,cpu_brand call sys_routine_seg_sel:put_string mov ebx,cpu_brnd1 call sys_routine_seg_sel:put_string ;loading and positioning the user program. mov ebx,message_5 call sys_routine_seg_sel:put_string mov esi,50 call load_relocate_program mov ebx,do_status call sys_routine_seg_sel:put_string mov [esp_pointer], esp ;Temporary storage stack pointer. mov ds,ax ;User program head index number. jmp far [0x10] ;Control to the user program (entry point). return_point: mov eax,core_data_seg_sel ;Switch back to the kernel data segment. mov ds,eax mov eax,core_stack_seg_sel ;Switch back to the kernel stack. mov ss,eax mov esp,[esp_pointer] mov ebx,message_6 call sys_routine_seg_sel:put_string hlt ;=============================================================================== SECTION core_trail ;------------------------------------------------------------------------------- core_end:
user.asm
;=============================================================================== ;FileName: user.asm ;Complie Method: nasm user.asm -o user.bin ;Descriptor: USER ;Author: by Taozai ;Date: 2015/02/04 ;=============================================================================== ;=============================================================================== SECTION header vstart=0 ;------------------------------------------------------------------------------- ; ; head info. ; program_length dd program_end ;#0x00 program length. header_len dd header_end ;#0x04 program head length. stack_seg dd 0 ;#0x08 stack selector. stack_len dd 1 ;#0x0c stack length. 4KB. prgentry dd start ;#0x10 program entry pointer. code_seg dd section.code.start ;#0x14 code segment position. code_len dd code_end ;#0x18 code segment length. data_seg dd section.data.start ;#0x1c data segment position. data_len dd data_end ;#0x20 data segment length. ; ; ; salt_items dd (header_end-salt)/256 ;#0x24 function counts. salt: ;#0x28 PrintString db '@PrintString' times 256-($-PrintString) db 0 TerminateProgram db '@TerminateProgram' times 256-($-TerminateProgram) db 0 ReadDiskData db '@ReadDiskData' times 256-($-ReadDiskData) db 0 header_end: ;=============================================================================== SECTION data vstart=0 ;------------------------------------------------------------------------------- buffer times 1024 db 0 message_1 db 0x0d,0x0a,0x0d,0x0a db '**********User program is runing**********' db 0x0d,0x0a,0 message_2 db ' Disk data:',0x0d,0x0a,0 data_end: ;******************************************************************************* [bits 32] ;******************************************************************************* ;=============================================================================== SECTION code vstart=0 ;------------------------------------------------------------------------------- start: mov eax,ds mov fs,eax mov eax,[stack_seg] mov ss,eax mov esp,0 mov eax,[data_seg] mov ds,eax mov ebx,message_1 call far [fs:PrintString] mov eax,100 mov ebx,buffer call far [fs:ReadDiskData] mov ebx,message_2 call far [fs:PrintString] mov ebx,buffer call far [fs:PrintString] jmp far [fs:TerminateProgram] code_end: ;=============================================================================== SECTION trail ;------------------------------------------------------------------------------- program_end: