版权声明:本文为博主jmh原创文章,未经博主允许不得转载。 https://blog.csdn.net/jmh1996/article/details/83099338
#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" \ //1.内核代码段的基地址(gdt表的第二项)2.INIT_TASK里面 进程0 的代码段的段基址,特权(计算)
"pushl $1f\n\t" \ //1f,formal向前找;仿照一个中断,模仿 int;用于翻特权级,翻到3特权
"iret\n" \ //依次弹栈,依次eip····
"1:\tmovl $0x17,%%eax\n\t" \ //3特权,特权级 究竟是什么?
"movw %%ax,%%ds\n\t" \
"movw %%ax,%%es\n\t" \
"movw %%ax,%%fs\n\t" \
"movw %%ax,%%gs" \
:::"ax")//对齐
本来没有什么说的,可是我们看前三句,为什么是
"movl %%esp,%%eax\n\t" \
"pushl $0x17\n\t" \
"pushl %%eax\n\t" \
假设0x17保存在栈的地址为x。那么此时eax就是x+4。压入栈的是x+4这个值。
而不是
"pushl $0x17\n\t" \
"movl %%esp,%%eax\n\t" \
"pushl %%eax\n\t" \
此时eax=x,压入栈的是x。
这是因为!在iret的时候,它的过程其实是:
pop eip
pop cs
pop eflag
pop tempesp
pop tempss
检查tempesp和tempss是否合理
如果合理:esp=tempesp;ss=tempss
否则:报错
在跟杨老师交流后,老师给了一个很好的提示:ESP,SS的恢复不是通过弹栈实现的,有点类似于CPU在弹玩EFLAG的时候,就知道了紧接着的就是ESP,SS寄存器,然后CPU会先将这里面的元素取出来,然后mov给esp,然后在mov给ss