grub boot.S调试

/* -*-Asm-*- */
/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 1999,2000,2001,2002,2005,2006,2007,2008,2009  Free Software Foundation, Inc.
 *
 *  GRUB is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  GRUB is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <grub/symbol.h>
#include <grub/machine/boot.h>

/*
 *  defines for the code go here
 */

    /* Print message string */
#define MSG(x)    movw $x, %si; call LOCAL(message)
#define ERR(x)    movw $x, %si; jmp LOCAL(error_message)

    .macro floppy
part_start:

LOCAL(probe_values):
    .byte    36, 18, 15, 9, 0

LOCAL(floppy_probe):
    pushw    %dx
/*
 *  Perform floppy probe.
 */
#ifdef __APPLE__
    LOCAL(probe_values_minus_one) = LOCAL(probe_values) - 1
    movw    MACRO_DOLLAR(LOCAL(probe_values_minus_one)), %si
#else
    movw    MACRO_DOLLAR(LOCAL(probe_values)) - 1, %si
#endif

LOCAL(probe_loop):
    /* reset floppy controller INT 13h AH=0 */
    xorw    %ax, %ax
    int    MACRO_DOLLAR(0x13)

    incw    %si
    movb    (%si), %cl

    /* if number of sectors is 0, display error and die */
    testb    %cl, %cl
    jnz    1f

/*
 * Floppy disk probe failure.
 */
    MSG(fd_probe_error_string)
    jmp    LOCAL(general_error)

/* "Floppy" */
fd_probe_error_string:    .asciz "Floppy"

1:
    /* perform read */
    movw    MACRO_DOLLAR(GRUB_BOOT_MACHINE_BUFFER_SEG), %bx
    movw    %bx, %es
    xorw    %bx, %bx
    movw    MACRO_DOLLAR(0x201), %ax
    movb    MACRO_DOLLAR(0), %ch
    movb    MACRO_DOLLAR(0), %dh
    int    MACRO_DOLLAR(0x13)

    /* if error, jump to "LOCAL(probe_loop)" */
    jc    LOCAL(probe_loop)

    /* %cl is already the correct value! */
    movb    MACRO_DOLLAR(1), %dh
    movb    MACRO_DOLLAR(79), %ch

    jmp    LOCAL(final_init)
    .endm

    .macro scratch

    /* scratch space */
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... */
    .endm

    .file    "boot.S"

    .text

    /* Tell GAS to generate 16-bit instructions so that this code works
       in real mode. */
    .code16

.globl _start, start;
_start:
start:
    /*
     * _start is loaded at 0x7c00 and is jumped to with CS:IP 0:0x7c00
     */

    /*
     * Beginning of the sector is compatible with the FAT/HPFS BIOS
     * parameter block.
     */

    jmp    LOCAL(after_BPB)
    nop    /* do I care about this ??? */

#ifdef HYBRID_BOOT
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop

    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop

    nop
    nop
    jmp    LOCAL(after_BPB)
#else
    /*
     * This space is for the BIOS parameter block!!!!  Don't change
     * the first jump, nor start the code anywhere but right after
     * this area.
     */

    .org GRUB_BOOT_MACHINE_BPB_START
    .org 4
#endif
#ifdef HYBRID_BOOT
    floppy
#else
    scratch
#endif

    .org GRUB_BOOT_MACHINE_BPB_END

    /* The offset of the end of BPB (BIOS Parameter Block).  */
    //#define GRUB_BOOT_MACHINE_BPB_END    0x5a
    /*
     * End of BIOS parameter block.
     */

LOCAL(kernel_address):
//内核的运行地址
    .word    GRUB_BOOT_MACHINE_KERNEL_ADDR
    //0x8000

#ifndef HYBRID_BOOT
//error 
    .org GRUB_BOOT_MACHINE_KERNEL_SECTOR
LOCAL(kernel_sector):
    .long    1
LOCAL(kernel_sector_high):
    .long    0
#endif


#ifdef HYBRID_BOOT
//error
#endif


    .org GRUB_BOOT_MACHINE_BOOT_DRIVE
    //0x64      
boot_drive:
    .byte 0xff    /* the disk to load kernel from */
            /* 0xff means use the boot drive */

LOCAL(after_BPB):

/* general setup */
    cli        /* we're not safe here! */
       
//1 byte
        /*
         * This is a workaround for buggy BIOSes which don't pass boot
         * drive correctly. If GRUB is installed into a HDD, check if
         * DL is masked correctly. If not, assume that the BIOS passed
         * a bogus value and set DL to 0x80, since this is the only
         * possible boot drive. If GRUB is installed into a floppy,
         * this does nothing (only jump).
         */
    .org GRUB_BOOT_MACHINE_DRIVE_CHECK
boot_drive_check:

   


//等待键盘输入字符'0'
    //sti 
    //movw    $0x1234,     %ax 
    //call print_start
    //movb    $0x00, %ah
    //movb    $0xff, %al
    //int     $0x16
    //cmpb    $0x0d, %al          //2 byte
    //jne        boot_drive_check                 //2 byte
    
  

    //nop
    //nop
    
    


    
    

    
    
    
    //jmp boot_drive_check
    

       //jmp     3f    /* grub-setup may overwrite this jump */
       // testb   $0x80, %dl  //3 byte
       // jz      2f  //2 byte
3:


    /* Ignore %dl different from 0-0x0f and 0x80-0x8f.  */
    //testb   $0x70, %dl  //3 byte
    //jz      1f   //2 byte

    //movw    %dx, %bx
    

    //AX,CX,DX,BX,SP,BP,SI,DI依次
    
2:    
    //movb    $0x80, %dl  //2 byte
1:
    //movw    %i4p, %bx
    /*
     * ljmp to the next instruction because some bogus BIOSes
     * jump to 07C0:0000 instead of 0000:7C00.
     */
    //ljmp    $0,    $real_start  //5 byte
    //切换cs寄存器的值
    //jmp real_start
    nop
    nop
    //此处改成短跳转也可以 但是不可以没有这条指令 
    //因为grub-install 程序会在此位置 90 90 填充2条nop指令
    //如果没有 后面的指令会前移到此位置 也就是会把后续指令nop
    //直接2 nop占位也可以
real_start: 
    /* set up %ds and %ss as offset from 0 */

    //movw    $0x66BB, %bx
    xorw    %ax, %ax   //2 byte
    movw    %ax, %ds   //2 byte
    movw    %ax, %ss   //2 byte

    //set up the REAL stack
    //movw  $GRUB_BOOT_MACHINE_STACK_SEG, %sp  //3 byte
    movw    $0x2000,   %sp
         
    sti        /* we're safe again */  //1 byte

wait_user_input:
    //movw    %dx,     %ax 
    //call print_start

    //movw    %bx,     %ax 
    //call print_start

    //movw    %si,     %ax 
    //call print_start

    //movw    %di,     %ax 
    //call print_start

    //movw    %bp,     %ax 
    //call print_start

    //movw    %sp,     %ax 
    //call print_start
    
    //movb    $0x00, %ah
    //movb    $0xff, %al
    //int     $0x16
    //cmpb    $0x0d, %al          //2 byte
    //jne        wait_user_input                 //2 byte

    

    /*
     *  Check if we have a forced disk reference here
     */
    movb   boot_drive, %al   //3 byte
    cmpb    $0xff, %al     //2 byte
    je    1f               //2 byte
    movb    %al, %dl     //2 byte
1:
    /* save drive reference first thing! */
    pushw    %dx   //1 byte
      

2:
    /* print a notification message on the screen */
    //MSG(notification_string)

    
    

    
    //6 byte
    //BE 80 7D        mov     si, 7D80h   3 byte
    //E8 17 01        call    sub_7DAA        ; Call Procedure  3byte

    //jmp 2b   //2字节
    /* set %si to the disk address packet */
    movw    $disk_address_packet, %si   //3 byte

    /* check if LBA is supported */
    movb    $0x41, %ah    //2 byte
    movw    $0x55aa, %bx  //3 byte
    int    $0x13  //2字节
     //DISK - Check for INT 13h Extensions
     //BX = 55AAh, DL = drive number
     //Return: CF set if not supported
     //AH = extensions version
     //BX = AA55h
     //CX = Interface support bit map


    /*
     *  %dl may have been clobbered by INT 13, AH=41H.
     *  This happens, for example, with AST BIOS 1.04.
     */
    
    popw    %dx   //1 byte
    //pushw    %dx   //1 byte

    /* use CHS if fails */
    jc    LOCAL(chs_mode)   //2 byte
    cmpw    $0xaa55, %bx  //4 byte
    jne    LOCAL(chs_mode)   //2 byte

    andw    $1, %cx       //3 byte
    jz    LOCAL(chs_mode)   //2 byte

LOCAL(lba_mode):
    //会进入这里
    //MSG(hd_probe_error_string)  //6 byte
    //jmp    LOCAL(lba_mode)  //3 byte
    //MSG(general_error_string)


    
    
    xorw    %ax, %ax      //2 byte
    movw    %ax, 4(%si)   //3 byte
    incw    %ax           //1 byte
    
    /* set the mode to non-zero */
    movb    %al, -1(%si)   //3 byte

    /* the blocks */
    movw    %ax, 2(%si)  //3 byte

    /* the size and the reserved byte */
    movw    $0x0010, (%si)  //4 byte

    /* the absolute address */
    movl    LOCAL(kernel_sector), %ebx  //5 byte
    movl    %ebx, 8(%si)        //4 byte
    movl    LOCAL(kernel_sector_high), %ebx  //5 byte
    movl    %ebx, 12(%si)   //4 byte

    /* the segment of buffer address */
    movw    $GRUB_BOOT_MACHINE_BUFFER_SEG, 6(%si)  //5 byte

/*
 * 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   //2 byte
    int    $0x13            //2 byte


    // 这次 INT 0x13 调用将完成 :
 // 通过扩展读 , 从磁盘读取由 kernel_sector 处8字节长度确定的某一扇区的内容到内存地址 0x70000(0x7000:0x0000) 处
 

    /* LBA read is not supported, so fallback to CHS.  */
    jc    LOCAL(chs_mode)  //2 byte

    movw    $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx  //3 byte
    jmp    LOCAL(copy_buffer)     //2 byte


/
//老硬盘的处理 没有走这条路 代码全部注释掉
LOCAL(chs_mode):
    /*
     *  Determine the hard disk geometry from the BIOS!
     *  We do this first, so that LS-120 IDE floppies work correctly.
     */

//nop
    MSG(read_error_string)   //6 byte
    jmp LOCAL(chs_mode)      //3 byte
    //MSG(general_error_string)
    //movb    $8, %ah   //2 byte
    //int    $0x13         //2 byte
    //jnc    LOCAL(final_init)   //2 byte

    //popw    %dx     //1 byte
    /*
     *  The call failed, so maybe use the floppy probe instead.
     */
    //testb    %dl, %dl     //2 byte
    //jnb    LOCAL(floppy_probe)   //4 byte

    /* Nope, we definitely have a hard disk, and we're screwed. */
    //ERR(hd_probe_error_string)  //6 byte

LOCAL(final_init):
    /* set the mode to zero */
    //movzbl    %dh, %eax
    //movb    %ah, -1(%si)

    /* save number of heads */
    //incw    %ax
    //movl    %eax, 4(%si)

    //movzbw    %cl, %dx
    //shlw    $2, %dx
    //movb    %ch, %al
    //movb    %dh, %ah

    /* save number of cylinders */
    //incw    %ax
    //movw    %ax, 8(%si)

    //movzbw    %dl, %ax
    //shrb    $2, %al

    /* save number of sectors */
    //movl    %eax, (%si)

setup_sectors:
    /* load logical sector start (top half) */
    //movl    LOCAL(kernel_sector_high), %eax

    //orl    %eax, %eax
    //jnz    LOCAL(geometry_error)

    /* load logical sector start (bottom half) */
    //movl    LOCAL(kernel_sector), %eax

    /* zero %edx */
    //xorl    %edx, %edx

    /* divide by number of sectors */
    //divl    (%si)

    /* save sector start */
    //movb    %dl, %cl

    //xorw    %dx, %dx    /* zero %edx */
    //divl    4(%si)        /* divide by number of heads */

    /* do we need too many cylinders? */
    //cmpw    8(%si), %ax
    //jge    LOCAL(geometry_error)

    /* normalize sector start (1-based) */
    //incb    %cl

    /* low bits of cylinder start */
    //movb    %al, %ch

    /* high bits of cylinder start */
    //xorb    %al, %al
    //shrw    $2, %ax
    //orb    %al, %cl

    /* save head start */
    //movb    %dl, %al

    /* restore %dl */
    //popw    %dx

    /* head start */
    //movb    %al, %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    $GRUB_BOOT_MACHINE_BUFFER_SEG, %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    LOCAL(read_error)

    //movw    %es, %bx
/


    
//拷贝程序
LOCAL(copy_buffer):
    /*
     * We need to save %cx and %si because the startup code in
     * kernel uses them without initializing them.
     */
    //这里需要保存 cx 和 si 的值
    //因为内核 startup 里面的代码未经初始化就使用了它( 其实是 diskboot.S 代码 )
 
    pusha
    pushw    %ds


    // 设置循环次数和源/目的串段寄存器和偏移指针
 // 设置完毕之后 , 寄存器值 :
 // CX = 0x100 ; ES:SI=0x8000:0x0000
 // LBA读 : DS:SI = 0x7000:0x0000
 // CHS读 : DS:SI = ?
 

    movw    $0x100, %cx
    movw    %bx, %ds
    xorw    %si, %si
    movw    $GRUB_BOOT_MACHINE_KERNEL_ADDR, %di
    movw    %si, %es

    cld
     //DF = 0 (方向标志)

    rep
    movsw

    // 操作串由 DS:SI 和 ES:DI 指定
 // 将 DS:SI 指向的字传送到 ES:DI 指向的内存单元
 // DF = 0 , 因此 SI += 2 ; DI += 2
 

    popw    %ds
    popa


    //movw    %si,     %ax 
    //call print_start
    //call LOCAL(wait_user_input)

    /* boot kernel */
    jmp    *(LOCAL(kernel_address))
     // 0x8000 处存放了 diskboot.S 生成的机器码
 // 至于 0x8000 处的 512 字节代码完成什么功能 , 见 diskboot.S 注释


//boot.S干的活: 
//1.磁盘自检查 确定为LBA模式  软盘和老式硬盘代码没有用到
//2.加载磁盘(diskboot.S)的第1扇区数据到0x7000:0x0000地址 一般boot.S放0扇区,即mbr扇区 接下来就是diskboot.S(1-60几扇区)
//3.加载内存0x7000:0x0000的1扇区内容到内存0x8000:0x0000,然后跳过去执行 内存数据搬运
//END OF MAIN LOOP


//出错处理部分
/*
 * BIOS Geometry translation error (past the end of the disk geometry!).
 */
LOCAL(geometry_error):
    ERR(geometry_error_string)

/*
 * Read error on the disk.
 */
LOCAL(read_error):
    movw    $read_error_string, %si
LOCAL(error_message):
    call    LOCAL(message)
LOCAL(general_error):
    MSG(general_error_string)

/* go here when you need to stop the machine hard after an error condition */
        /* tell the BIOS a boot failure, which may result in no effect */
        int    $0x18
LOCAL(stop):
    jmp    LOCAL(stop)
//完犊子了

notification_string:    .asciz "GRUB "
geometry_error_string:    .asciz "Ggxm"
hd_probe_error_string:    .asciz "Hard Disk"
read_error_string:    .asciz "Read"
general_error_string:    .asciz " Error\r\n"


//终端输出字符串的功能函数
/*
 * 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 */
LOCAL(message):
    lodsb
    cmpb    $0, %al
    jne    1b    /* if not end of string, jmp to display */
    ret

print_start:

    pusha
    pushw    %ds

    //初始化寄存器
    //movw    $0x12ab,     %ax     //将需要转换的值存入eax
    mov     $0,          %di
    movw    $0x000f,     %dx
loop_ascii:
    movw    %ax,    %bx
    imul    $4, %di, %cx
    and     %dx,    %bx
    ror     %cl,     %bx
    cmpb    $10,     %bl
    jnc     max_num_is_9     
    addb    $0x30,   %bl
    jmp     modify_index
max_num_is_9:
    addb    $0x37,   %bl
modify_index:              
    rol     $4,      %dx
    mov     $5,      %cx
    sub     %di,     %cx
    movb    %bl,     debug_out_buf( , %ecx, 1 )
//AT&T汇编以及Intel汇编说明    
//3>变址寻址
//  AT&T: _variable(%eax)
//  Intel: [eax + _variable]
//  AT&T: _array(, %eax,4)
//  Intel: [eax*4+_array]
//  AT&T: _array(%ebx, %eax,8)
//  Intel: [ebx + eax*8 + _array]
  
  
  
    cmp     $3,      %di
    jnc     print
    inc     %di
    jmp     loop_ascii

print:
    movw $debug_out_buf, %si; 
    call LOCAL(message)
    //jmp .

    popw    %ds
    popa
    ret

//.section .bss

//.lcomm
debug_out_buf:
    .byte    '0'
    .byte    'x'
    .byte    '1'
    .byte    '2'
    .byte    '3'
    .byte    '4'
    .byte    '\r'
    .byte    '\n'
    .long    0

LOCAL(wait_user_input):
    pusha
    pushw    %ds
1:
    movb    $0x00, %ah
    movb    $0xff, %al
    int     $0x16
    cmpb    $0x0d, %al                //2 byte
    jne        1b    //2 byte
    popw    %ds
    popa
    ret        
    
    
    
                

//从0x1b0开始 由于有org指令 所以代码不能越过这个位置
    /*
     *  Windows NT breaks compatibility by embedding a magic
     *  number here.
     */
#ifdef HYBRID_BOOT
    .org 0x1b0
LOCAL(kernel_sector):
    //diskboot.S文件的扇区低地址 4字节 lba_mode
    .long    1
LOCAL(kernel_sector_high):
    //diskboot.S文件的扇区高地址 4字节 lba_mode
    .long    0
#endif
    .org GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC
    //0x1b8 windows系统使用的魔幻数 6字节
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?
    */

    .org GRUB_BOOT_MACHINE_PART_START
    //Boot.h (include\grub\i386\pc):#define GRUB_BOOT_MACHINE_PART_START    0x1be    
    //分区表的开始位置 4个分区项 每项16字节
#ifndef HYBRID_BOOT
    floppy
#else
    scratch
#endif

    .org GRUB_BOOT_MACHINE_PART_END
    //#define GRUB_BOOT_MACHINE_PART_END    0x1fe
    //the last 2 bytes in the sector 0 contain the signature
    .word    GRUB_BOOT_MACHINE_SIGNATURE
    //#define GRUB_BOOT_MACHINE_SIGNATURE    0xaa55
    //在0扇区的最后2字节是签名魔幻数 55 aa
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值