move_to_user_mode()一个push esp的疑问

版权声明:本文为博主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

猜你喜欢

转载自blog.csdn.net/jmh1996/article/details/83099338