您的位置:首页 > 其它

程序的动态加载和执行

2015-02-07 18:09 253 查看
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:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐