📄 asm.s
字号:
/* store new segment */ movw 0x4(%esp), %ax movw %ax, segment shll $4, %eax /* generate linear address */ addl %eax, %ebx /* set up to pass the partition where stage2 is located in */ movl EXT_C(current_partition), %eax movl %eax, (EXT_C(install_partition)-EXT_C(main))(%ebx) /* set up to pass the drive where stage2 is located in */ movb EXT_C(current_drive), %dl /* set up to pass the second sector of stage2 */ movl 0xc(%esp), %ecx call EXT_C(prot_to_real) .code16 movl %ecx, %ebp#ifdef ABSOLUTE_WITHOUT_ASTERISK DATA32 ADDR32 ljmp (offset)#else DATA32 ADDR32 ljmp *(offset)#endif .code32#endif /* STAGE1_5 */ /* * These next two routines, "real_to_prot" and "prot_to_real" are structured * in a very specific way. Be very careful when changing them. * * NOTE: Use of either one messes up %eax and %ebp. */ENTRY(real_to_prot) .code16 cli /* load the GDT register */ DATA32 ADDR32 lgdt gdtdesc /* turn on protected mode */ movl %cr0, %eax orl $CR0_PE_ON, %eax movl %eax, %cr0 /* jump to relocation, flush prefetch queue, and reload %cs */ DATA32 ljmp $PROT_MODE_CSEG, $protcseg /* * The ".code32" directive only works in GAS, the GNU assembler! * This gets out of "16-bit" mode. */ .code32protcseg: /* reload other segment registers */ movw $PROT_MODE_DSEG, %ax movw %ax, %ds movw %ax, %es movw %ax, %fs movw %ax, %gs movw %ax, %ss /* put the return address in a known safe location */ movl (%esp), %eax movl %eax, STACKOFF /* get protected mode stack */ movl protstack, %eax movl %eax, %esp movl %eax, %ebp /* get return address onto the right stack */ movl STACKOFF, %eax movl %eax, (%esp) /* zero %eax */ xorl %eax, %eax /* return on the old (or initialized) stack! */ retENTRY(prot_to_real) /* just in case, set GDT */ lgdt gdtdesc /* save the protected mode stack */ movl %esp, %eax movl %eax, protstack /* get the return address */ movl (%esp), %eax movl %eax, STACKOFF /* set up new stack */ movl $STACKOFF, %eax movl %eax, %esp movl %eax, %ebp /* set up segment limits */ movw $PSEUDO_RM_DSEG, %ax movw %ax, %ds movw %ax, %es movw %ax, %fs movw %ax, %gs movw %ax, %ss /* this might be an extra step */ ljmp $PSEUDO_RM_CSEG, $tmpcseg /* jump to a 16 bit segment */tmpcseg: .code16 /* clear the PE bit of CR0 */ movl %cr0, %eax andl $CR0_PE_OFF, %eax movl %eax, %cr0 /* flush prefetch queue, reload %cs */ DATA32 ljmp $0, $realcsegrealcseg: /* we are in real mode now * set up the real mode segment registers : DS, SS, ES */ /* zero %eax */ xorl %eax, %eax movw %ax, %ds movw %ax, %es movw %ax, %fs movw %ax, %gs movw %ax, %ss /* restore interrupts */ sti /* return on new stack! */ DATA32 ret .code32/* * int biosdisk_int13_extensions (int ax, int drive, void *dap) * * Call IBM/MS INT13 Extensions (int 13 %ax=AX) for DRIVE. DAP * is passed for disk address packet. If an error occurs, return * non-zero, otherwise zero. */ENTRY(biosdisk_int13_extensions) pushl %ebp movl %esp, %ebp pushl %esi pushl %ebx /* compute the address of disk_address_packet */ movl 0x10(%ebp), %eax movw %ax, %si xorw %ax, %ax shrl $4, %eax movw %ax, %cx /* save the segment to cx */ /* drive */ movb 0xc(%ebp), %dl /* ax */ movw 0x8(%ebp), %bx /* enter real mode */ call EXT_C(prot_to_real) .code16 movw %bx, %ax movw %cx, %ds int $0x13 /* do the operation */ movb %ah, %dl /* save return value */ /* clear the data segment */ xorw %ax, %ax movw %ax, %ds /* back to protected mode */ DATA32 call EXT_C(real_to_prot) .code32 movb %dl, %al /* return value in %eax */ popl %ebx popl %esi popl %ebp ret /* * int biosdisk_standard (int ah, int drive, int coff, int hoff, int soff, * int nsec, int segment) * * Call standard and old INT13 (int 13 %ah=AH) for DRIVE. Read/write * NSEC sectors from COFF/HOFF/SOFF into SEGMENT. If an error occurs, * return non-zero, otherwise zero. */ENTRY(biosdisk_standard) pushl %ebp movl %esp, %ebp pushl %ebx pushl %edi pushl %esi /* set up CHS information */ movl 0x10(%ebp), %eax movb %al, %ch movb 0x18(%ebp), %al shlb $2, %al shrw $2, %ax movb %al, %cl movb 0x14(%ebp), %dh /* drive */ movb 0xc(%ebp), %dl /* segment */ movw 0x20(%ebp), %bx /* save nsec and ah to %di */ movb 0x8(%ebp), %ah movb 0x1c(%ebp), %al movw %ax, %di /* enter real mode */ call EXT_C(prot_to_real) .code16 movw %bx, %es xorw %bx, %bx movw $3, %si /* attempt at least three times */1: movw %di, %ax int $0x13 /* do the operation */ jnc 2f /* check if successful */ movb %ah, %bl /* save return value */ /* if fail, reset the disk system */ xorw %ax, %ax int $0x13 decw %si cmpw $0, %si je 2f xorb %bl, %bl jmp 1b /* retry */2: /* back to protected mode */ DATA32 call EXT_C(real_to_prot) .code32 movb %bl, %al /* return value in %eax */ popl %esi popl %edi popl %ebx popl %ebp ret/* * int check_int13_extensions (int drive) * * Check if LBA is supported for DRIVE. If it is supported, then return * the major version of extensions, otherwise zero. */ENTRY(check_int13_extensions) pushl %ebp movl %esp, %ebp pushl %ebx /* drive */ movb 0x8(%ebp), %dl /* enter real mode */ call EXT_C(prot_to_real) .code16 movb $0x41, %ah movw $0x55aa, %bx int $0x13 /* do the operation */ /* check the result */ jc 1f cmpw $0xaa55, %bx jne 1f movb %ah, %bl /* save the major version into %bl */ /* check if AH=0x42 is supported if FORCE_LBA is zero */ movb EXT_C(force_lba), %al testb %al, %al jnz 2f andw $1, %cx jnz 2f 1: xorb %bl, %bl2: /* back to protected mode */ DATA32 call EXT_C(real_to_prot) .code32 movb %bl, %al /* return value in %eax */ popl %ebx popl %ebp ret/* * int get_diskinfo_standard (int drive, unsigned long *cylinders, * unsigned long *heads, unsigned long *sectors) * * Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an * error occurs, then return non-zero, otherwise zero. */ENTRY(get_diskinfo_standard) pushl %ebp movl %esp, %ebp pushl %ebx pushl %edi /* drive */ movb 0x8(%ebp), %dl /* enter real mode */ call EXT_C(prot_to_real) .code16 movb $0x8, %ah int $0x13 /* do the operation */ /* check if successful */ testb %ah, %ah jnz 1f /* bogus BIOSes may not return an error number */ testb $0x3f, %cl /* 0 sectors means no disk */ jnz 1f /* if non-zero, then succeed */ /* XXX 0x60 is one of the unused error numbers */ movb $0x60, %ah1: movb %ah, %bl /* save return value in %bl */ /* back to protected mode */ DATA32 call EXT_C(real_to_prot) .code32 /* restore %ebp */ leal 0x8(%esp), %ebp /* heads */ movb %dh, %al incl %eax /* the number of heads is counted from zero */ movl 0x10(%ebp), %edi movl %eax, (%edi) /* sectors */ xorl %eax, %eax movb %cl, %al andb $0x3f, %al movl 0x14(%ebp), %edi movl %eax, (%edi) /* cylinders */ shrb $6, %cl movb %cl, %ah movb %ch, %al incl %eax /* the number of cylinders is counted from zero */ movl 0xc(%ebp), %edi movl %eax, (%edi) xorl %eax, %eax movb %bl, %al /* return value in %eax */ popl %edi popl %ebx popl %ebp ret#if 0 /* * int get_diskinfo_floppy (int drive, unsigned long *cylinders, * unsigned long *heads, unsigned long *sectors) * * Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an * error occurs, then return non-zero, otherwise zero. */ENTRY(get_diskinfo_floppy) pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi /* drive */ movb 0x8(%ebp), %dl /* enter real mode */ call EXT_C(prot_to_real) .code16 /* init probe value */ movl $probe_values-1, %esi1: xorw %ax, %ax int $0x13 /* reset floppy controller */ incw %si movb (%si), %cl cmpb $0, %cl /* probe failed if zero */ je 2f /* perform read */ movw $SCRATCHSEG, %ax movw %ax, %es xorw %bx, %bx movw $0x0201, %ax movb $0, %ch movb $0, %dh int $0x13 /* FIXME: Read from floppy may fail even if the geometry is correct. So should retry at least three times. */ jc 1b /* next value */ /* succeed */ jmp 2f probe_values: .byte 36, 18, 15, 9, 0 2: /* back to protected mode */ DATA32 call EXT_C(real_to_prot) .code32 /* restore %ebp */ leal 0x8(%esp), %ebp /* cylinders */ movl 0xc(%ebp), %eax movl $80, %ebx movl %ebx, (%eax) /* heads */ movl 0x10(%ebp), %eax movl $2, %ebx movl %ebx, (%eax) /* sectors */ movl 0x14(%ebp), %eax movzbl %cl, %ebx movl %ebx, (%eax) /* return value in %eax */ xorl %eax, %eax cmpb $0, %cl jne 3f incl %eax /* %eax = 1 (non-zero) */3: popl %esi popl %ebx popl %ebp ret#endif /* Source files are splitted, as they have different copyrights. */#ifndef STAGE1_5# include "setjmp.S"# include "apm.S"#endif /* ! STAGE1_5 */ #ifndef STAGE1_5/* get_code_end() : return the address of the end of the code * This is here so that it can be replaced by asmstub.c. */ENTRY(get_code_end) /* will be the end of the bss */# if defined(HAVE_END_SYMBOL) movl $end, %eax# elif defined(HAVE_USCORE_END_SYMBOL) movl $_end, %eax# endif shrl $2, %eax /* Round up to the next word. */ incl %eax shll $2, %eax ret#endif /* ! STAGE1_5 *//* * * get_memsize(i) : return the memory size in KB. i == 0 for conventional * memory, i == 1 for extended memory * BIOS call "INT 12H" to get conventional memory size * BIOS call "INT 15H, AH=88H" to get extended memory size * Both have the return value in AX. * */ENTRY(get_memsize) push %ebp push %ebx mov 0xc(%esp), %ebx call EXT_C(prot_to_real) /* enter real mode */ .code16 cmpb $0x1, %bl DATA32 je xext int $0x12 DATA32 jmp xdonexext: movb $0x88, %ah int $0x15xdone: movw %ax, %bx DATA32 call EXT_C(real_to_prot) .code32 movw %bx, %ax pop %ebx pop %ebp ret#ifndef STAGE1_5/* * * get_eisamemsize() : return packed EISA memory map, lower 16 bits is * memory between 1M and 16M in 1K parts, upper 16 bits is * memory above 16M in 64K parts. If error, return -1. * BIOS call "INT 15H, AH=E801H" to get EISA memory map, * AX = memory between 1M and 16M in 1K parts. * BX = memory above 16M in 64K parts. * */ENTRY(get_eisamemsize) push %ebp push %ebx call EXT_C(prot_to_real) /* enter real mode */ .code16 movw $0xe801, %ax int $0x15 shll $16, %ebx movw %ax, %bx DATA32 call EXT_C(real_to_prot) .code32 movl $0xFFFFFFFF, %eax cmpb $0x86, %bh je xnoteisa movl %ebx, %eaxxnoteisa: pop %ebx pop %ebp ret/* * * get_mmap_entry(addr, cont) : address and old continuation value (zero to * start), for the Query System Address Map BIOS call. * * Sets the first 4-byte int value of "addr" to the size returned by * the call. If the call fails, sets it to zero. * * Returns: new (non-zero) continuation value, 0 if done. * * NOTE: Currently hard-coded for a maximum buffer length of 1024. */ENTRY(get_mmap_entry) push %ebp push %ebx push %edi push %esi /* place address (+4) in ES:DI */ movl 0x14(%esp), %eax addl $4, %eax movl %eax, %edi andl $0xf, %edi shrl $4, %eax movl %eax, %esi /* set continuation value */ movl 0x18(%esp), %ebx /* set default maximum buffer size */ movl $0x14, %ecx /* set EDX to 'SMAP' */ movl $0x534d4150, %edx call EXT_C(prot_to_real) /* enter real mode */ .code16 movw %si, %es movl $0xe820, %eax int $0x15 DATA32 jc xnosmap cmpl $0x534d4150, %eax DATA32 jne xnosmap cmpl $0x14, %ecx DATA32 jl xnosmap cmpl $0x400, %ecx DATA32 jg xnosmap DATA32 jmp xsmapxnosmap: movl $0, %ecxxsmap: DATA32 call EXT_C(real_to_prot) .code32 /* write length of buffer (zero if error) into "addr" */ movl 0x14(%esp), %eax movl %ecx, (%eax) /* set return value to continuation */ movl %ebx, %eax pop %esi pop %edi pop %ebx pop %ebp ret/* * get_rom_config_table() * * Get the linear address of a ROM configuration table. Return zero, * if fails. */ ENTRY(get_rom_config_table) pushl %ebp pushl %ebx /* zero %ebx for simplicity */ xorl %ebx, %ebx call EXT_C(prot_to_real) .code16 movw $0xc0, %ax int $0x15 jc no_rom_table testb %ah, %ah jnz no_rom_table movw %es, %dx jmp found_rom_table no_rom_table: xorw %dx, %dx xorw %bx, %bx found_rom_table: DATA32 call EXT_C(real_to_prot) .code32 /* compute the linear address */ movw %dx, %ax shll $4, %eax addl %ebx, %eax popl %ebx popl %ebp ret/* * int get_vbe_controller_info (struct vbe_controller *controller_ptr) * * Get VBE controller information. */ENTRY(get_vbe_controller_info) pushl %ebp movl %esp, %ebp pushl %edi pushl %ebx /* Convert the linear address to segment:offset */ movl 8(%ebp), %eax movl %eax, %edi andl $0x0000000f, %edi shrl $4, %eax movl %eax, %ebx call EXT_C(prot_to_real) .code16 movw %bx, %es movw $0x4F00, %ax int $0x10 movw %ax, %bx DATA32 call EXT_C(real_to_prot) .code32 movzwl %bx, %eax popl %ebx popl %edi popl %ebp ret /* * int get_vbe_mode_info (int mode_number, struct vbe_mode *mode_ptr) * * Get VBE mode information. */ENTRY(get_vbe_mode_info) pushl %ebp movl %esp, %ebp pushl %edi pushl %ebx /* Convert the linear address to segment:offset */ movl 0xc(%ebp), %eax movl %eax, %edi andl $0x0000000f, %edi shrl $4, %eax movl %eax, %ebx /* Save the mode number in %cx */ movl 0x8(%ebp), %ecx call EXT_C(prot_to_real) .code16 movw %bx, %es movw $0x4F01, %ax int $0x10 movw %ax, %bx DATA32 call EXT_C(real_to_prot) .code32 movzwl %bx, %eax popl %ebx popl %edi popl %ebp ret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -