⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 1.html

📁 介绍linux下文件和设备编程
💻 HTML
📖 第 1 页 / 共 5 页
字号:
<center><A HREF="#Content">[目录]</A></center><hr><br><A NAME="I360" ID="I360"></A><center><b><font size=+2>内核解压</font></b></center><br>概述<br>----<p>1) Linux的初始内核映象以gzip压缩文件的格式存放在zImage或bzImage之中, 内核的自举代码将它解压到1M内存开始处. 在内核初始化时, 如果加载了压缩的initrd映象, 内核会将它解压到内存盘中, 这两处解压过程都使用了lib/inflate.c文件.<p>2) inflate.c是从gzip源程序中分离出来的, 包含了一些对全局数据的直接引用, 在使用时需要直接嵌入到代码中. gzip压缩文件时总是在前32K字节的范围内寻找重复的字符串进行编码, 在解压时需要一个至少为32K字节的解压缓冲区, 它定义为window[WSIZE].inflate.c使用get_byte()读取输入文件, 它被定义成宏来提高效率. 输入缓冲区指针必须定义为inptr, inflate.c中对之有减量操作. inflate.c调用flush_window()来输出window缓冲区中的解压出的字节串, 每次输出长度用outcnt变量表示. 在flush_window()中, 还必须对输出字节串计算CRC并且刷新crc变量.&nbsp; 在调用gunzip()开始解压之前, 调用makecrc()初始化CRC计算表. 最后gunzip()返回0表示解压成功.<p><br>3) zImage或bzImage由16位引导代码和32位内核自解压映象两个部分组成. 对于zImage, 内核自解压映象被加载到物理地址0x1000, 内核被解压到1M的部位. 对于bzImage, 内核自解压映象被加载到1M开始的地方, 内核被解压为两个片段, 一个起始于物理地址0x2000-0x90000,另一个起始于高端解压映象之后, 离1M开始处不小于低端片段最大长度的区域. 解压完成后,这两个片段被合并到1M的起始位置.<p><br>解压根内存盘映象文件的代码<br>--------------------------<p>; drivers/block/rd.c<br>#ifdef BUILD_CRAMDISK<p>/*<br> * gzip declarations<br> */<p>#define OF(args)&nbsp; args&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; 用于函数原型声明的宏<br>#ifndef memzero<br>#define memzero(s, n)&nbsp;&nbsp;&nbsp;&nbsp; memset ((s), 0, (n))<br>#endif<br>typedef unsigned char&nbsp; uch;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 定义inflate.c所使用的3种数据类型<br>typedef unsigned short ush;<br>typedef unsigned long&nbsp; ulg;<br>#define INBUFSIZ 4096&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用户输入缓冲区尺寸<br>#define WSIZE 0x8000&nbsp;&nbsp;&nbsp; /* window size--must be a power of two, and */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp; at least 32K for zip's deflate method */<p>static uch *inbuf;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用户输入缓冲区,与inflate.c无关<br>static uch *window;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 解压窗口<br>static unsigned insize;&nbsp; /* valid bytes in inbuf */<br>static unsigned inptr;&nbsp;&nbsp; /* index of next byte to be processed in inbuf */<br>static unsigned outcnt;&nbsp; /* bytes in output buffer */<br>static int exit_code;<br>static long bytes_out;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 总解压输出长度,与inflate.c无关<br>static struct file *crd_infp, *crd_outfp;<p>#define get_byte()&nbsp; (inptr<br>/* Diagnostic functions (stubbed out) */ 一些调试宏<br>#define Assert(cond,msg)<br>#define Trace(x)<br>#define Tracev(x)<br>#define Tracevv(x)<br>#define Tracec(c,x)<br>#define Tracecv(c,x)<p>#define STATIC static<p>static int&nbsp; fill_inbuf(void);<br>static void flush_window(void);<br>static void *malloc(int size);<br>static void free(void *where);<br>static void error(char *m);<br>static void gzip_mark(void **);<br>static void gzip_release(void **);<p>#include &quot;../../lib/inflate.c&quot;<p>static void __init *malloc(int size)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return kmalloc(size, GFP_KERNEL);<br>}<p>static void __init free(void *where)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kfree(where);<br>}<p>static void __init gzip_mark(void **ptr)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; 读取用户一个标记<br>}<p>static void __init gzip_release(void **ptr)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; 归还用户标记<br>}<p>/* ===========================================================================<br> * Fill the input buffer. This is called only when the buffer is empty<br> * and at least one byte is really needed.<br> */<p>static int __init fill_inbuf(void) 填充输入缓冲区<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (exit_code) return -1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insize = crd_infp-&gt;f_op-&gt;read(crd_infp, inbuf, INBUFSIZ,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (insize == 0) return -1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inptr = 1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return inbuf[0];<br>}<p>/* ===========================================================================<br> * Write the output window window[0..outcnt-1] and update crc and bytes_out.<br> * (Used for the decompressed data only.)<br> */<p>static void __init flush_window(void) 输出window缓冲区中outcnt个字节串<br>{<br>&nbsp;&nbsp;&nbsp; ulg c = crc;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* temporary variable */<br>&nbsp;&nbsp;&nbsp; unsigned n;<br>&nbsp;&nbsp;&nbsp; uch *in, ch;<p>&nbsp;&nbsp;&nbsp; crd_outfp-&gt;f_op-&gt;write(crd_outfp, window, outcnt,<br>&nbsp;&nbsp;&nbsp; in = window;<br>&nbsp;&nbsp;&nbsp; for (n = 0; n &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ch = *in++;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; c = crc_32_tab[((int)c ^ ch)&nbsp; 0xff] ^ (c &gt;&gt; 8); 计算输出串的CRC<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; crc = c;<br>&nbsp;&nbsp;&nbsp; bytes_out += (ulg)outcnt; 刷新总字节数<br>&nbsp;&nbsp;&nbsp; outcnt = 0;<br>}<p>static void __init error(char *x) 解压出错调用的函数<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printk(KERN_ERR &quot;%s&quot;, x);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit_code = 1;<br>}<p><br>static int __init<br>crd_load(struct file * fp, struct file *outfp)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int result;<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insize = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* valid bytes in inbuf */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inptr = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* index of next byte to be processed in inbuf */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outcnt = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* bytes in output buffer */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit_code = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bytes_out = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; crc = (ulg)0xffffffffL; /* shift register contents */<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; crd_infp = fp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; crd_outfp = outfp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inbuf = kmalloc(INBUFSIZ, GFP_KERNEL);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (inbuf == 0) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printk(KERN_ERR &quot;RAMDISK: Couldn't allocate gzip buffer\n&quot;);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; window = kmalloc(WSIZE, GFP_KERNEL);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (window == 0) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printk(KERN_ERR &quot;RAMDISK: Couldn't allocate gzip window\n&quot;);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kfree(inbuf);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; makecrc();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = gunzip();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kfree(inbuf);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kfree(window);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return result;<br>}<p>#endif&nbsp; /* BUILD_CRAMDISK */<p>32位内核自解压代码<br>------------------<p>; arch/i386/boot/compressed/head.S<p>.text<br>#include &middot;<br>#include<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .globl startup_32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于zImage该入口地址为0x1000; 对于bzImage为0x101000<br>startup_32:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cld<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cli<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl $(__KERNEL_DS),%eax<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl %eax,%ds<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl %eax,%es<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl %eax,%fs<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl %eax,%gs<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lss SYMBOL_NAME(stack_start),%esp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # 自解压代码的堆栈为misc.c中定义的16K字节的数组<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xorl %eax,%eax<br>1:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; incl %eax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # check that A20 really IS enabled<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl %eax,0x000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # loop forever if it isn't<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmpl %eax,0x100000<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; je 1b<p>/*<br> * Initialize eflags.&nbsp; Some BIOS's leave bits like NT set.&nbsp; This would<br> * confuse the debugger if this code is traced.<br> * XXX - best to initialize before switching to protected mode.<br> */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pushl $0<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; popfl<br>/*<br> * Clear BSS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 清除解压程序的BSS段<br> */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xorl %eax,%eax<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl $ SYMBOL_NAME(_edata),%edi<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl $ SYMBOL_NAME(_end),%ecx<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; subl %edi,%ecx<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cld<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rep<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stosb<br>/*<br> * Do the decompression, and jump to the new kernel..<br> */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; subl $16,%esp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # place for structure on the stack<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl %esp,%eax<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pushl %esi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # real mode pointer as second arg<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pushl %eax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # address of structure as first arg<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call SYMBOL_NAME(decompress_kernel)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; orl&nbsp; %eax,%eax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # 如果返回非零,则表示为内核解压为低端和高端的两个片断<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jnz&nbsp; 3f<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; popl %esi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # discard address<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; popl %esi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # real mode pointer<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xorl %ebx,%ebx<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ljmp $(__KERNEL_CS), $0x100000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # 运行start_kernel<p>/*<br> * We come here, if we were loaded high.<br> * We need to move the move-in-place routine down to 0x1000<br> * and then start it with the buffer addresses in registers,<br> * which we got from the stack.<br> */<br>3:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl $move_routine_start,%esi<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl $0x1000,%edi<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl $move_routine_end,%ecx<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; subl %esi,%ecx<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; addl $3,%ecx<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shrl $2,%ecx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # 按字取整<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cld<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rep<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movsl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # 将内核片断合并代码复制到0x1000区域, 内核的片段起始为0x2000<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; popl %esi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # discard the address<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; popl %ebx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # real mode pointer<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; popl %esi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # low_buffer_start&nbsp; 内核低端片段的起始地址<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; popl %ecx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # lcount&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 内核低端片段的字节数量<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; popl %edx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # high_buffer_start 内核高端片段的起始地址<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; popl %eax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # hcount&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 内核高端片段的字节数量<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl $0x100000,%edi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 内核合并的起始地址<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cli&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # make sure we don't get interrupted<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine<p>/*<br> * Routine (template) for moving the decompressed kernel in place,<br> * if we were high loaded. This _must_ PIC-code !<br> */<br>move_routine_start:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl %ecx,%ebp<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shrl $2,%ecx<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rep<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movsl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # 按字拷贝第1个片段<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl %ebp,%ecx<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; andl $3,%ecx<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rep<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movsb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # 传送不完全字<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl %edx,%esi<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl %eax,%ecx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # NOTE: rep movsb won't move if %ecx == 0<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; addl $3,%ecx<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shrl $2,%ecx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # 按字对齐<br>&nbsp;&nbsp;&nbs

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -