VESA编程试验之二


  
进行了VESA编程试验之二。启动了分页机制,在保护模式下访问图形模式的显存。加载了IDT。
借用了赵炯博士的linux-0.00-redhat的boot.s代码。编译要用minix所用的as86和ld86(apt-get install bin86)。boot.s构成了 512字节的引导扇区,在ld86链接之后要跳过32字节的a.out头。其他的代码(视为loader)添加在其之后构成boot.img,在512字节之外。 boot.s读取loader到0x10000,然后被移动到0x1000处。之后jmp 0x100:0跳到它。
boot.s( for bochs ):
!	boot.s
!
! It then loads the system at 0x10000, using BIOS interrupts. Thereafter
! it disables all interrupts, changes to protected mode, and calls the 

BOOTSEG = 0x07c0
SYSSEG  = 0x1000			! system loaded at 0x10000 (65536).
SYSLEN  = 18				! sectors occupied.

entry start
start:
	jmpi	go,#BOOTSEG
go:	mov	ax,cs
	mov	ds,ax
	mov	ss,ax
	mov	sp,#0x400		! arbitrary value >>512

! ok, we've written the message, now
load_system:
	mov	dx,#0x0000
	mov	cx,#0x0002
	mov	ax,#SYSSEG
	mov	es,ax
	xor	bx,bx
	mov	ax,#0x200+SYSLEN
	int 	0x13


       !jmp 0x0:0
       !jmp 0x1000:0

	jnc	ok_load

! now we want to move to protected mode ...
ok_load:
	cli			! no interrupts allowed !
	mov	ax, #SYSSEG
	mov	ds, ax
	!xor	ax, ax
	mov	ax, #0x100
	mov	es, ax
	mov	cx, #0x2000
	sub	si,si
	sub	di,di
	rep
	movw


        jmp  0x100:0

	mov	ax, #BOOTSEG
	mov	ds, ax
	lidt	idt_48		! load idt with 0,0
	lgdt	gdt_48		! load gdt with whatever appropriate

! absolute address 0x00000, in 32-bit protected mode.
	mov	ax,#0x0001	! protected mode (PE) bit
	lmsw	ax		! This is it!
	jmpi	0,8		! jmp offset 0 of segment 8 (cs)

gdt:	.word	0,0,0,0		! dummy

	.word	0x07FF		! 8Mb - limit=2047 (2048*4096=8Mb)
	.word	0x0000		! base address=0x00000
	.word	0x9A00		! code read/exec
	.word	0x00C0		! granularity=4096, 386

	.word	0x07FF		! 8Mb - limit=2047 (2048*4096=8Mb)
	.word	0x0000		! base address=0x00000
	.word	0x9200		! data read/write
	.word	0x00C0		! granularity=4096, 386

idt_48: .word	0		! idt limit=0
	.word	0,0		! idt base=0L
gdt_48: .word	0x7ff		! gdt limit=2048, 256 GDT entries
	.word	0x7c00+gdt,0	! gdt base = 07xxx
.org 510
	.word   0xAA55

 
boot3.S中打开了分页机制,现在的做法是试验性的,把线性地址映射到同样的物理地址。页目录存放在地址0x200000起始处, 页表存放在$0x201000起始处。 (lidt idt_48不知为何未能成功,只好从栈上内存加载6个字节。)
boot3.S( for bochs ):
.code16gcc
.global _start
.text
.align 4


_start:

###### A20 ########

     pushl  %eax
     pushl  %ecx            # needed to save, (demo code is like this)

     cli
     

     xor  %eax,  %eax 
     #movl  $0,  number

     movw $0x2401 ,  %ax
     #movw $0x2400 ,  %ax
     int  $0x15             #al 00-disabled 01-enabled

     movw $0x2402 ,  %ax
     int  $0x15             #al 00-disabled 01-enabled


     sti

     popl   %ecx
     popl   %eax


###################

##### VESA #######

     pushw %di
     pushl %eax
     pushl %ecx
     pushw %bx

     movw  $0x8000, %di

     movw  $0x4115, %bx
     movw $0x4f02, %ax

     int  $0x10

     movb  %ah,  number


     popw %bx
     popl %ecx
     popl %eax
     popw %di
 
#########################

########  protected mode ########
     cli
 

     xor   %ax, %ax
     mov   %ax, %ds
     call setup_idt

     lgdt   gdt_48
     movl   %cr0,  %eax
     orl    $1 , %eax
     movl   %eax, %cr0

     ljmp     $0x8, $protcseg
#################################

####### write video ram ####
.code32
write_vram:

     sti

     pushl  %eax
     pushw  %ds
     pushw  %di


     movl $0xe0000000, %eax
     addl $720000,      %eax
     movw   %fs,  %cx

     movw   %cx,  %di

     calll  main2          
     jmp .                 # remove these two lines to show assembly drawing


     movl $800, %ecx
loop:

     movl $0x00ff0000, (%eax)

     addl $3,   %eax
     subl $1,   %ecx
     cmp  $0,   %ecx
     jnz  loop
 
     popw  %di
     popw  %ds
     popl  %eax

     jmp .

##################


.code16gcc
##### base code ###
base:
   pushw %ds
   pushw %es
   pushw %ss

   movw %cs, %ax
   movw %ax, %ds
   movw %ax, %es
   movw %ax, %ss

    pushw %sp   

    movw $stack, %ax
    movw  %ax, %sp

    calll  main2

    popw %sp
    movw $stack, %sp

    popw %ss
    popw %es
    popw %ds

#   movw $0x4c00, %ax
#   int $0x21            #return to DOS

    hlt 


message:
   .string "Hello, world!\n\0"

.global display_str
display_str:


.org  .+0x40
stack:


.code32
protcseg:
 
     sti


     movw  $0x10,  %ax
     movw %ax, %ds        # this is indispensable

     movw %ax, %ss


      ######## paging ###################
     pushl  %eax
     pushl  %ebx
     pushl  %ecx
     pushl  %edx

     movl $1024, %edx

     movl $0x201, %eax
     shl  $12, %eax
     orl  $0x7, %eax

     movl $0x200000, %ebx
     movl $4096,  %ecx
     
loop_page_dir:
     movl  %eax , (%ebx)
     addl  %ecx, %eax
     addl   $4,  %ebx

     subl $1, %edx
     cmp $0, %edx
     jnz loop_page_dir
     
         ####
     movl $(1024*1024), %edx

     movl $0, %eax
     shl $12, %eax
     orl  $0x7, %eax

     movl $0x201000, %ebx
     movl $4096,  %ecx
     
loop_page_table:
     movl  %eax , (%ebx)
     addl  %ecx, %eax
     addl   $4,  %ebx

     subl $1, %edx
     cmp $0, %edx
     jnz loop_page_table
     

     popl %edx
     popl %ecx
     popl %ebx
     popl %eax





      mov  $0x200000, %eax
      mov  %eax, %cr3
      mov  %cr0, %eax
      or $0x80000000, %eax
      mov %eax, %cr0
      
      ###########################


######### return to real mode ######
#.code16gcc
#     cli

#     movl   %cr0,  %eax
#     andl    $0xfffffffe , %eax
#     movl   %eax, %cr0



     #jmp     $0x0, $write_vram    #ljmp $0x08, $write_vram #jmp  write_vram
     jmp    write_vram    #ljmp $0x08, $write_vram #jmp  write_vram

####################################
.code16gcc
setup_idt:
    lea  ignore_int, %edx
    movl  $0x00080000, %eax
    movw %dx,%ax
    movw $0x8e00, %dx
    lea idt, %edi
    mov $256, %ecx
rp_idt:  movl  %eax,(%edi)
    movl  %edx, 4(%edi)
    addl  $8, %edi
    dec  %ecx
    jne  rp_idt

     movl  $0,  -4(%esp)
     movl  $0,  -8(%esp)
     lea idt, %edi
     movl %edi, -4(%esp)
     movw  $2047,-6(%esp)
     lidt  -6(%esp)
    #  lidt idt_48
    retw


#setup_gdt:
#     movl  $0,  -4(%esp)
#     movl  $0,  -8(%esp)
#     lea gdt, %edi
#     movl %edi, -4(%esp)
#     movw  $0x1f,-6(%esp)
#     lgdt  -6(%esp)
#    retw



.align 8
ignore_int:
    push %ds
    pushl %eax
    movl $0x10, %eax
    mov %ax, %ds
    movl $67, %eax
    #call write_char
    popl %eax
    pop %ds
    iretw


.code32
gdt:   .word 0,0,0,0
    .word  0xffff
    .word  0x0000
    .word  0x9a00
    .word  0x00cf

    .word  0xffff
    .word  0x0000
    .word  0x9200
    .word  0x00cf


      .word 0,0,0,0  

gdt_48:    .word  0x1f
           .long  gdt




.data
.align 8
idt:   .fill  256,8,0
idt_48:   
       .word 256*8-1
       .long idt
 
boot3.c( for bochs ):
__asm__(".code32\n");


void display_str(char* str, short length);

int number ;
int number2;

void main2()
{
   char* str;

   number2 = number;
      char* pAddress = (char*)0xe0000000;
      pAddress +=300*800 + 100*3;
      for(int i = 0; i < 2400-200*3; i++)   
      {
         *pAddress = 255;
	 pAddress += 1;
      }
      while(1)
	 ;
}
 
编译脚本如下,loader链接指定起始位置为0x1000,即其被移动到的位置:
make3.sh(for bochs):
#!/bin/bash
   rm -f boot *.o *.out boot.img    disassem.asm

	as86 -o boot.o boot.s
	ld86 -s -o boot boot.o
   as --32 boot3.S -o boot3_S.o  
   gcc -c -m32 boot3.c  -o boot3_c.o
   ld -Ttext 0x1000  -m elf_i386  boot3_S.o  boot3_c.o   -o  boot.elf
   #ld -Ttext 0x7c00  -m elf_i386  boot3_S.o  boot3_c.o   -o  boot.elf
     objdump -D -m i8086   boot.elf  >  disassem.asm
   objcopy -j .text  -j .rodata   -O binary  boot.elf  boot.out
	dd bs=32 if=boot of=Image skip=1
	cat boot.out >> Image
    mv Image boot.img
 
运行bochs配置文件如下:
bochsrc(for bochs):
config_interface: textconfig
#display_library: sdl
#romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xf0000
romimage: file=/usr/share/bochs/BIOS-bochs-latest
megs: 32
vgaromimage: file=/usr/share/vgabios/vgabios.bin
floppya: type=1_44, 1_44="boot.img", status=inserted
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata1: enabled=0, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11
ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9
#ata0-master: type=disk, path="", mode=flat, cylinders=1024, heads=16, spt=63
ata0-slave: type=cdrom, path="/dev/cdrom", status=inserted

boot: floppy

#ips: 1000000
floppy_bootsig_check: disabled=0
log: /dev/stdout
panic: action=ask
error: action=report
info: action=report
debug: action=ignore
debugger_log: -
com1: enabled=1, dev=/dev/ttyS0
parport1: enabled=1, file="/dev/lp0"
sb16: midimode=1, midi=/dev/midi00, wavemode=1, wave=/dev/dsp, loglevel=2, log=/dev/stdout, dmatimer=600000
vga_update_interval: 300000
keyboard_serial_delay: 250
keyboard_paste_delay: 100000
#floppy_command_delay: 500
mouse: enabled=1
private_colormap: enabled=0
#ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:00, ethmod=linux, ethdev=eth0
#keyboard_mapping: enabled=0, map=/usr/share/bochs/keymaps/x11-pc-de.map
#keyboard_type: mf
#user_shortcut: keys=ctrlaltdel
#magic_break: enabled=1
#cmosimage: cmos.img
#load32bitOSImage: os=nullkernel, path=../kernel.img, iolog=../vga_io.log
#load32bitOSImage: os=linux, path=../linux.img, iolog=../vga_io.log, initrd=../initrd.img
#i440fxsupport: enabled=1
#usb1: enabled=1, ioaddr=0xFF80, irq=10
#text_snapshot_check: enable
 
运行命令:bochs -f ./bochsrc。Bochs调试命令:info tab及page linear_address。
效果图和以前是一样的。如前图:
(汇编版)

(c语言版)


至此试验之二就告完成。结论是:启动虚拟存储后,可写0xe0000000线性地址的VESA (LFB模式的)显存。 仍然参阅了试验一中的书籍和一些网文等, 表示谢意。
源文件打包在此:boot3_bochs_0.9994.tgz

  

More powered by