`
redheart_2006
  • 浏览: 21810 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类

x86汇编语言 从实模式到保护模式 疑问汇总

 
阅读更多
x86汇编语言 从实模式到保护模式书中,14.4.6 中段长度为什么是0xffffe 。
该段长度是4K,ESP初始值为0000 0000, 0xFFFFFFFF-0xFFFFEFFF = 4KB
实际使用的段界限是0xFFFFE * 0x1000+0xFFF=0xFFFFEFFF
从而得到0xFFFFE

   ;创建0特权级堆栈
         mov ecx,4096
         mov eax,ecx                        ;为生成堆栈高端地址做准备
         mov [es:esi+0x1a],ecx
         shr dword [es:esi+0x1a],12         ;登记0特权级堆栈尺寸到TCB
         call sys_routine_seg_sel:allocate_memory
         add eax,ecx                        ;堆栈必须使用高端地址为基地址
         mov [es:esi+0x1e],eax              ;登记0特权级堆栈基地址到TCB
        mov ebx,0xffffe                    ;段长度(界限)
         mov ecx,0x00c09600                 ;4KB粒度,读写,特权级0
         call sys_routine_seg_sel:make_seg_descriptor
         mov ebx,esi                        ;TCB的基地址
         call fill_descriptor_in_ldt
         ;or cx,0000_0000_0000_0000          ;设置选择子的特权级为0
         mov [es:esi+0x22],cx               ;登记0特权级堆栈选择子到TCB
         mov dword [es:esi+0x24],0          ;登记0特权级堆栈初始ESP到TCB

---------------
iret/iretd 怎么会自动切换到程序管理器任务上边去呢? 这个中间的处理逻辑是怎么的。。这个过程是处理器固化处理吗? ----找到当前的TSS的头部的前一个任务的TSS指针(即程序管理器任务)更新相关的寄存器数据切换过去的

书中只有一句话,在295 的中间,  “第374行,通过iretd指令转换到前一个任务”

这个应该是我表述有问题吧。。。 我现在的理解 :检查NT位,如果为1,找到当前的TSS的头部的前一个任务的TSS指针(即程序管理器任务)更新相关的寄存器数据切换过去的

NT为1,表示是嵌套任务返回,当前TSS中的链接字段保存前一任务的TSS的选择子,取出该选择子,进行任务切换完成返回。

如是NT为0,表示当前任务内返回, 从stack弹出返回指针EIP及CS,然后弹出EFLAG值。 弹出CS中RPL,确定返回后的特权级。接下来与RET类似。

In Protected Mode, the action of the IRET instruction depends on the settings of the NT (nested task) and VM flags in the EFLAGS register and the VM flag in the EFLAGS image stored on the current stack. Depending on the setting of these flags, the processor performs the following types of interrupt returns:
• Return from virtual-8086 mode.
• Return to virtual-8086 mode.
• Intra-privilege level return.
• Inter-privilege level return.
• Return from nested task (task switch).

If the NT flag (EFLAGS register) is cleared, the IRET instruction performs a far return from the interrupt procedure, without a task switch. The code segment being returned to must be equally or less privileged than the interrupt handler routine (as indicated by the RPL field of the code segment selector popped from the stack).
As with a real-address mode interrupt return, the IRET instruction pops the return instruction pointer, return code segment selector, and EFLAGS image from the stack to the EIP, CS, and EFLAGS registers, respectively, and then resumes execution of the interrupted program or procedure. If the return is to another privilege level, the IRET instruction also pops the stack pointer and SS from the stack, before resuming  program execution. If the return is to virtual-8086 mode, the processor also pops the
data segment registers from the stack.
If the NT flag is set, the IRET instruction performs a task switch (return) from a nested task (a task called with a CALL instruction, an interrupt, or an exception) back to the calling or interrupted task. The updated state of the task executing the IRET
instruction is saved in its TSS. If the task is re-entered later, the code that follows the IRET instruction is executed.
If the NT flag is set and the processor is in IA-32e mode, the IRET instruction causes a general protection exception.
In 64-bit mode, the instruction’s default operation size is 32 bits. Use of the REX.W prefix promotes operation to 64 bits (IRETQ). See the summary chart at the beginning of this section for encoding data and limits.




--------以下是请教关东鼠侠QQ交流记录-----------------------------------------
你先回到前面p210
【團长】关东鼠 2017/3/20 星期一 09:58:40

看看书上那几页。

【連長】^鱼小雄^ 2017/3/20 星期一 09:59:14

好的
10:00:52
【團长】关东鼠 2017/3/20 星期一 10:00:52

p.214
10:05:24
【團长】关东鼠 2017/3/20 星期一 10:05:24

整明白没有?

【連長】^鱼小雄^ 2017/3/20 星期一 10:05:36

还没有。。

【連長】^鱼小雄^ 2017/3/20 星期一 10:05:43

有点笨啊。。
【團长】关东鼠 2017/3/20 星期一 10:06:08

不是笨,是栈的界限这一块确实很绕很烧脑。

【連長】^鱼小雄^ 2017/3/20 星期一 10:06:15

描述符中的段界限值*0x1000+0xFFF
【團长】关东鼠 2017/3/20 星期一 10:06:42

我来问你,我们给ESP寄存器的初值是多少?

【連長】^鱼小雄^ 2017/3/20 星期一 10:06:50

从14章这个代码里看,他的长度4K

【連長】^鱼小雄^ 2017/3/20 星期一 10:06:52

0

【連長】^鱼小雄^ 2017/3/20 星期一 10:07:19

ESP 中的初值应该是0
10:07:35
【團长】关东鼠 2017/3/20 星期一 10:07:35

好,压栈时,是先减ESP。如果操作数是2个字节,那么,压栈时,ESP的新值是多少?

【連長】^鱼小雄^ 2017/3/20 星期一 10:08:16

FFFFE

【連長】^鱼小雄^ 2017/3/20 星期一 10:08:21

FFFE
【團长】关东鼠 2017/3/20 星期一 10:09:01

糊涂了吧?ESP是32位的寄存器。

【連長】^鱼小雄^ 2017/3/20 星期一 10:09:07

是的。。

【連長】^鱼小雄^ 2017/3/20 星期一 10:09:12

FFFF FFFE
10:09:36
【團长】关东鼠 2017/3/20 星期一 10:09:36

所以,每次压栈时,ESP的值必须在栈界限值以内。
【團长】关东鼠 2017/3/20 星期一 10:10:48

对于栈来说,实际使用的段界限,是不允许访问的最低端地址。
10:11:38
【連長】^鱼小雄^ 2017/3/20 星期一 10:11:38

恩,对的。。

【連長】^鱼小雄^ 2017/3/20 星期一 10:11:46

所以是用0 - 4k
【團长】关东鼠 2017/3/20 星期一 10:12:44

所以,我们这里是界限值0xFFFFE
所以,在这里,实际使用的段界限是0xFFFFE * 0x1000+0xFFFF=0xFFFFEFFF
【團长】关东鼠 2017/3/20 星期一 10:12:58

或者说,ESP必须大小0xFFFFEFFF
【團长】关东鼠 2017/3/20 星期一 10:13:03

大于
【團长】关东鼠 2017/3/20 星期一 10:13:21

0xFFFFFFFF-0xFFFFEFFF = 4KB

【連長】^鱼小雄^ 2017/3/20 星期一 10:13:36

恩,是的,终于搞明白了



【連長】^鱼小雄^ 2017/3/20 星期一 10:13:55

这个要备注下

【團长】关东鼠 2017/3/20 星期一 10:14:15

再版的时候,朕也改一下,说得更清楚些。
【團长】linux-果 2017/3/20 星期一 10:14:19

155.94.235.113这打开速度还可以吧
【團长】linux-果 2017/3/20 星期一 10:14:23

155.94.235.113


10:19:08
【團长】关东鼠 2017/3/20 星期一 10:19:08

@^鱼小雄^ 你可以将这个问题写成一个博客,朕率文武百官前去拜读。

【連長】^鱼小雄^ 2017/3/20 星期一 10:19:25

哈哈,好的。。。
  • 大小: 98.4 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics