Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2621074
  • 博文数量: 258
  • 博客积分: 9440
  • 博客等级: 少将
  • 技术积分: 6998
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-03 10:28
个人简介

-- linux爱好者,业余时间热衷于分析linux内核源码 -- 目前主要研究云计算和虚拟化相关的技术,主要包括libvirt/qemu,openstack,opennebula架构和源码分析。 -- 第五届云计算大会演讲嘉宾 微博:@Marshal-Liu

文章分类

全部博文(258)

文章存档

2016年(1)

2015年(4)

2014年(16)

2013年(22)

2012年(41)

2011年(59)

2010年(40)

2009年(75)

分类: LINUX

2009-09-17 18:48:28

 
 
#include
 
#define ABS(x) (x-_start+0x7c00)    //计算物理地址,不依赖编译器
 /* Print message string */
#define MSG(x) movw $ABS(x), %si; call message
 /* XXX: binutils-2.9.1.0.x doesn't produce a short opcode for this. */
#define MOV_MEM_TO_AL(x) .byte 0xa0;  .word x //这个不用管它,只是为了实现兼容性用了机器码
 
 .file "stage1.S"
 .text
 .code16
.globl _start; _start:
 jmp after_BPB
 nop /* do I care about this ??? */
 . = _start + 4            //跳过上面两条指令
 /* scratch space  BIOS参数的定义*/
mode:
 .byte 0
disk_address_packet: 
sectors:
 .long 0
heads:
 .long 0
cylinders:
 .word 0
sector_start:
 .byte 0
head_start:
 .byte 0
cylinder_start:
 .word 0
 /* more space... */
 . = _start + STAGE1_BPBEND
 /*
  * End of BIOS parameter block.
  */
/*与启动有关的参数的定义*/
stage1_version: 
 .byte COMPAT_VERSION_MAJOR, COMPAT_VERSION_MINOR
boot_drive: 
 .byte GRUB_INVALID_DRIVE /* the disk to load stage2 from */
force_lba:
 .byte 0
stage2_address:
 .word 0x8000
stage2_sector:
 .long 1
stage2_segment:
 .word 0x800
after_BPB:
/* general setup */
 cli  /* we're not safe here! */
 
boot_drive_check:    /*这段代码有什么用? jmp 1f 后面的代码能执行吗?我没看明白*/
 jmp 1f
 testb $0x80, %dl
 jnz 1f
 movb $0x80, %dl
1: 
 /*
  * ljmp to the next instruction because some bogus BIOSes
  * jump to 07C0:0000 instead of 0000:7C00.
  */
 ljmp $0, $ABS(real_start)            /*cs = 0*/
real_start: 
 /* set up %ds and %ss as offset from 0 */
 xorw %ax, %ax
 movw %ax, %ds
 movw %ax, %ss
 /* set up the REAL stack */
 movw $STAGE1_STACKSEG, %sp            /*STAGE1_STACKSEG = 0x2000*/          
 sti  /* we're safe again */
 /*
  *  Check if we have a forced disk reference here
  */
 MOV_MEM_TO_AL(ABS(boot_drive)) /* movb  ABS(boot_drive), %al */   
 cmpb $GRUB_INVALID_DRIVE, %al     /* 如果boot_drive=0xff,则表示从默认的位置加载stage2
                                       * 如果不是默认,把驱动器号保存在dl中
                                       */
 je 1f
 movb %al, %dl
1:
 /* save drive reference first thing! */
 pushw %dx                                    /*不是默认的话,保存才是有用的,否则没用*/
 /* print a notification message on the screen */
 MSG(notification_string)
 /* do not probe LBA if the drive is a floppy */
 testb $STAGE1_BIOS_HD_FLAG, %dl    /*如果是软盘,即STAGE1_STACKSEG=0,直接跳入chs模式*/
 jz chs_mode
   
 /* check if LBA is supported */
 movb $0x41, %ah          /*此时dl=80,ah=41h,bx=0x55aa,int 13h 检测第一块硬盘的CF位*/
 movw $0x55aa, %bx              /*即检查是否支持LBA寻址,不支持则CF=1*/
 int $0x13
       /**
        *AH 41h = function number for extensions check
      *DL drive index (e.g. 1st HDD = 80h)
      *BX 55AAh
        *CF Set On Not Present, Clear If Present
        ***/
 /*
  *  %dl may have been clobbered by INT 13, AH=41H.
  *  This happens, for example, with AST BIOS 1.04.
  */
 popw %dx
 pushw %dx
 /* use CHS if fails */
 jc chs_mode
 cmpw $0xaa55, %bx       /*测试后,正常情况下bx=0xaa55*/
 jne chs_mode
 /* check if AH=0x42 is supported if FORCE_LBA is zero */
 MOV_MEM_TO_AL(ABS(force_lba)) /* movb ABS(force_lba), %al */
 testb %al, %al
 jnz lba_mode
 andw $1, %cx                 /*CX Interface support bitmask:
                             * 1 - Device Access using the packet structure
                             * 2 - Drive Locking and Ejecting
                             * 4 - Enhanced Disk Drive Support (EDD)
                              */
 jz chs_mode
 
lba_mode:
 /* save the total number of sectors */
 movl 0x10(%si), %ecx            /*这是在干什么*/
 /* set %si to the disk address packet */
 movw $ABS(disk_address_packet), %si          /* si指向BIOS的参数*/
 /* set the mode to non-zero   mode =1*/
 movb $1, -1(%si)
 
 movl ABS(stage2_sector), %ebx
 /* the size and the reserved byte */
 movw $0x0010, (%si)                  /**/
 /* the blocks */
 movw $1, 2(%si)
 
 /* the absolute address (low 32 bits) */
 movl %ebx, 8(%si)
 /* the segment of buffer address */
 movw $STAGE1_BUFFERSEG, 6(%si)
 xorl %eax, %eax
 movw %ax, 4(%si)
 movl %eax, 12(%si)
 
/*
 * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory
 * Call with %ah = 0x42
 *   %dl = drive number
 *   %ds:%si = segment:offset of disk address packet
 * Return:
 *   %al = 0x0 on success; err code on failure
 */
 movb $0x42, %ah
 int $0x13
 /* LBA read is not supported, so fallback to CHS.  */
 jc chs_mode
 movw $STAGE1_BUFFERSEG, %bx
 jmp copy_buffer
  
chs_mode: 
 /*
  *  Determine the hard disk geometry from the BIOS!
  *  We do this first, so that LS-120 IDE floppies work correctly.
  */
 movb $8, %ah
 int $0x13      /*INT 13h AH=08h: Read Drive Parameters AH Return Code
                          *DL number of hard disk drives
                          *DH logical last index of heads = number_of - 1 (because index starts with 0)
                          *CX logical last index of cylinders = number_of - 1 (because index starts with 0)
                            */
 jnc final_init    /* CF Set On Error, Clear If No Error */
     
 /*
  *  The call failed, so maybe use the floppy probe instead.
  */
 testb $STAGE1_BIOS_HD_FLAG, %dl
 jz floppy_probe
 /* Nope, we definitely have a hard disk, and we're screwed. */
 jmp hd_probe_error
final_init:
 
 movw $ABS(sectors), %si
 /* set the mode to zero */
 movb $0, -1(%si)

 /* save number of heads */
 xorl %eax, %eax
 movb %dh, %al
 incw %ax
 movl %eax, 4(%si)
 xorw %dx, %dx
 movb %cl, %dl
 shlw $2, %dx
 movb %ch, %al
 movb %dh, %ah
 /* save number of cylinders */
 incw %ax
 movw %ax, 8(%si)
 xorw %ax, %ax
 movb %dl, %al
 shrb $2, %al
 /* save number of sectors */
 movl %eax, (%si)
setup_sectors:
 /* load logical sector start (bottom half) */
 movl ABS(stage2_sector), %eax
 /* zero %edx */
 xorl %edx, %edx
 /* divide by number of sectors */
 divl (%si)
 /* save sector start */
 movb %dl, 10(%si)
 xorl %edx, %edx /* zero %edx */
 divl 4(%si)  /* divide by number of heads */
 
 /* save head start */
 movb %dl, 11(%si)
 /* save cylinder start */
 movw %ax, 12(%si)
 /* do we need too many cylinders? */
 cmpw 8(%si), %ax
 jge geometry_error
/*
 *  This is the loop for taking care of BIOS geometry translation (ugh!)
 */
 /* get high bits of cylinder */
 movb 13(%si), %dl
 shlb $6, %dl  /* shift left by 6 bits */
 movb 10(%si), %cl /* get sector */
 incb %cl  /* normalize sector (sectors go
     from 1-N, not 0-(N-1) ) */
 orb %dl, %cl /* composite together */
 movb 12(%si), %ch /* sector+hcyl in cl, cylinder in ch */
 /* restore %dx */
 popw %dx
 
 /* head number */
 movb 11(%si), %dh
/*
 * BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
 * Call with %ah = 0x2
 *   %al = number of sectors
 *   %ch = cylinder
 *   %cl = sector (bits 6-7 are high bits of "cylinder")
 *   %dh = head
 *   %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
 *   %es:%bx = segment:offset of buffer
 * Return:
 *   %al = 0x0 on success; err code on failure
 */
 movw $STAGE1_BUFFERSEG, %bx
 movw %bx, %es /* load %es segment with disk buffer */
 xorw %bx, %bx /* %bx = 0, put it at 0 in the segment */
 movw $0x0201, %ax /* function 2 */
 int $0x13
 jc read_error
 movw %es, %bx
 
copy_buffer:
 movw ABS(stage2_segment), %es
 /*
  * We need to save %cx and %si because the startup code in
  * stage2 uses them without initializing them.
  */
 pusha
 pushw %ds
 
 movw $0x100, %cx
 movw %bx, %ds
 xorw %si, %si
 xorw %di, %di
 
 cld
 
 rep
 movsw
 popw %ds
 popa
 /* boot stage2 */
 jmp *(stage2_address)
/* END OF MAIN LOOP */
/*
 * BIOS Geometry translation error (past the end of the disk geometry!).
 */
geometry_error:
 MSG(geometry_error_string)
 jmp general_error
/*
 * Disk probe failure.
 */
hd_probe_error:
 MSG(hd_probe_error_string)
 jmp general_error
/*
 * Read error on the disk.
 */
read_error:
 MSG(read_error_string)
general_error:
 MSG(general_error_string)
/* go here when you need to stop the machine hard after an error condition */
stop: jmp stop
notification_string: .string "GRUB "
geometry_error_string: .string "Geom"
hd_probe_error_string: .string "Hard Disk"
read_error_string: .string "Read"
general_error_string: .string " Error"
/*
 * message: write the string pointed to by %si
 *
 *   WARNING: trashes %si, %ax, and %bx
 */
 /*
  * Use BIOS "int 10H Function 0Eh" to write character in teletype mode
  * %ah = 0xe %al = character
  * %bh = page %bl = foreground color (graphics modes)
  */
1:
 movw $0x0001, %bx
 movb $0xe, %ah
 int $0x10  /* display a byte */
message:
 lodsb
 cmpb $0, %al
 jne 1b /* if not end of string, jmp to display */
 ret
 /*
  *  Windows NT breaks compatibility by embedding a magic
  *  number here.
  */
 . = _start + STAGE1_WINDOWS_NT_MAGIC
nt_magic: 
 .long 0
 .word 0
 /*
  *  This is where an MBR would go if on a hard disk.  The code
  *  here isn't even referenced unless we're on a floppy.  Kinda
  *  sneaky, huh?
  */
part_start: 
 . = _start + STAGE1_PARTSTART
probe_values:
 .byte 36, 18, 15, 9, 0%3
阅读(3014) | 评论(0) | 转发(0) |
0

上一篇:int 13h 详解

下一篇:80386 汇编基础

给主人留下些什么吧!~~