,%gs lss SYMBOL_NAME(stack_start),%esp # 自解压代码的堆栈为misc.c中定义的16K字节的数组 xorl %eax,%eax 1: incl %eax # check that A20 really IS enabled movl %eax,0x000000 # loop forever if it isn't cmpl %eax,0x100000 je 1b pushl $0 popfl xorl %eax,%eax movl $ SYMBOL_NAME(_edata),%edi movl $ SYMBOL_NAME(_end),%ecx subl %edi,%ecx cld rep stosb subl $16,%esp # place for structure on the stack movl %esp,%eax pushl %esi # real mode pointer as second arg pushl %eax # address of structure as first arg call SYMBOL_NAME(decompress_kernel) orl %eax,%eax # 如果返回非零,则表示为内核解压为低端和高端的两个片断 jnz 3f popl %esi # discard address popl %esi # real mode pointer xorl %ebx,%ebx ljmp $(__KERNEL_CS), $0x100000 # 运行start_kernel 3: movl $move_routine_start,%esi movl $0x1000,%edi movl $move_routine_end,%ecx subl %esi,%ecx addl $3,%ecx shrl $2,%ecx # 按字取整 cld rep movsl # 将内核片断合并代码复制到0x1000区域, 内核的片段起始为0x2000 popl %esi # discard the address popl %ebx # real mode pointer popl %esi # low_buffer_start 内核低端片段的起始地址 popl %ecx # lcount 内核低端片段的字节数量 popl %edx # high_buffer_start 内核高端片段的起始地址 popl %eax # hcount 内核高端片段的字节数量 movl $0x100000,%edi 内核合并的起始地址 cli # make sure we don't get interrupted ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine move_routine_start: movl %ecx,%ebp shrl $2,%ecx rep movsl # 按字拷贝第1个片段 movl %ebp,%ecx andl $3,%ecx rep movsb # 传送不完全字 movl %edx,%esi movl %eax,%ecx # NOTE: rep movsb won't move if %ecx == 0 addl $3,%ecx shrl $2,%ecx # 按字对齐 rep movsl # 按字拷贝第2个片段 movl %ebx,%esi # Restore setup pointer xorl %ebx,%ebx ljmp $(__KERNEL_CS), $0x100000 # 运行start_kernel move_routine_end: ; arch/i386/boot/compressed/misc.c #define OF(args) args #define STATIC static #undef memset #undef memcpy #define memzero(s, n) memset ((s), 0, (n)) ypedef unsigned char uch; typedef unsigned short ush; typedef unsigned long ulg; #define WSIZE 0x8000 static uch *inbuf; static uch window[WSIZE]; static unsigned insize = 0; static unsigned inptr = 0; static unsigned outcnt = 0; #define ASCII_FLAG 0x01 #define CONTINUATION 0x02 #define EXTRA_FIELD 0x04 #define ORIG_NAME 0x08 #define COMMENT 0x10 #define ENCRYPTED 0x20 #define RESERVED 0xC0 #define get_byte() (inptr #ifdef DEBUG # define Assert(cond,msg) {if(!(cond)) error(msg);} # define Trace(x) fprintf x # define Tracev(x) {if (verbose) fprintf x ;} # define Tracevv(x) {if (verbose>1) fprintf x ;} # define Tracec(c,x) {if (verbose (c)) fprintf x ;} # define Tracecv(c,x) {if (verbose>1 (c)) fprintf x ;} #else # define Assert(cond,msg) # define Trace(x) # define Tracev(x) # define Tracevv(x) # define Tracec(c,x) # define Tracecv(c,x) #endif static int fill_inbuf(void); static void flush_window(void); static void error(char *m); static void gzip_mark(void **); static void gzip_release(void **); static unsigned char *real_mode; #define EXT_MEM_K (*(unsigned short *)(real_mode + 0x2)) #ifndef STANDARD_MEMORY_BIOS_CALL #define ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0)) #endif #define SCREEN_INFO (*(struct screen_info *)(real_mode+0)) extern char input_data[]; extern int input_len; static long bytes_out = 0; static uch *output_data; static unsigned long output_ptr = 0; static void *malloc(int size); static void free(void *where); static void error(char *m); static void gzip_mark(void **); static void gzip_release(void **); static void puts(const char *); extern int end; static long free_mem_ptr = (long) static long free_mem_end_ptr; #define INPLACE_MOVE_ROUTINE 0x1000 内核片段合并代码的运行地址 #define LOW_BUFFER_START 0x2000 内核低端解压片段的起始地址 #de |