标签:CS %% move eax 描述符 mode 堆栈 pushl user
/* * IRET * 当使用IRET指令返回到相同保护级别的任务时,也就是当前的CS中的DPL和堆栈中的DPL相同时 * IRET会从堆栈弹出代码段选择子及指令指针分别到CS与IP寄存器, * 并弹出标志寄存器内容到EFLAGS寄存器。 * * 当使用IRET指令返回到一个不同的保护级别时,也就是当前的CS中的DPL和堆栈中的DPL不同时 * IRET不仅会从堆栈弹出以上内容, * 还会弹出堆栈段选择子及堆栈指针分别到SS与SP寄存器。 * * * 我们知道当前系统使用了特权模式0, * movl %%esp,%%eax, 将当前的栈顶指针存放进入eax * pushl $0x17,17的二进制为00010111,表示权限为3,索引为2的段选择子,为数据段描述符,在局部描述符中 * pushl %%eax, 将原有的esp入栈 * pushfl, 将eflags 入栈 * pushl $0x0f, 0xf的二进制为00001111, 表示权限为3,索引为1的段选择子 为代码段选择符,在局部描述符中 * pushl $1f, 将如下标号1处的地址入栈 * iret 由于弹出的CS(0x0f)当前的CS(0x08)因此依次弹出IP,CS, EFLAGS, SS, SP * 根据构造好的栈进行转化到用户空间 * 紧接着执行如下 * movl $0x17,%%eax,设置数据段的描述符,此时系统继续运行下一跳指令 * * 由此我们可以看出来,转到用户空间后使用了本地描述符表的代码段描述符和数据段描述符 * 堆栈仍然使用了内核态的堆栈,但是权限不一样,task0的用户空间栈使用了内核的task_stack * 任务0是一个特殊进程,它的数据段和代码段直接映射到内核代码和数据空间 * 即从物理地址0开始的640KB内存空间,其地址是内核代码使用的堆栈 * 本地描述表在sched_init函数中已经进行了初始化 * */ #define move_to_user_mode() \ __asm__ ("movl %%esp,%%eax\n\t" \ "pushl $0x17\n\t" \ "pushl %%eax\n\t" \ "pushfl\n\t" \ "pushl $0x0f\n\t" \ "pushl $1f\n\t" \ "iret\n" \ "1:\tmovl $0x17,%%eax\n\t" \ "movw %%ax,%%ds\n\t" \ "movw %%ax,%%es\n\t" \ "movw %%ax,%%fs\n\t" \ "movw %%ax,%%gs" \ :::"ax")
标签:CS,%%,move,eax,描述符,mode,堆栈,pushl,user 来源: https://www.cnblogs.com/sudochen/p/16646382.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。