BackupGGCode / writeos

Write Your Own OS with Free and Open Source Software (Chinese)
1 stars 1 forks source link

chapter3/1/loader.S #6

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
/* chapter3/1/loader.S

   Author: Wenbo Yang <solrex@gmail.com> <http://solrex.cn>

   This file is part of the source code of book "Write Your Own OS with Free
   and Open Source Software". Homepage @ <http://share.solrex.cn/WriteOS/>.

   This file is licensed under the GNU General Public License; either
   version 3 of the License, or (at your option) any later version. */

#include "pm.h"

.code16
.text
    jmp LABEL_BEGIN     /* jump over the .data section. */

/* NOTE! Wenbo-20080512: Actually here we put the normal .data section into
   the .code section. For application SW, it is not allowed. However, we are
   writting an OS. That is OK. Because there is no OS to complain about
   that behavior. :) */

/* Global Descriptor Table */
LABEL_GDT:          Descriptor  0,                        0, 0
LABEL_DESC_CODE32:  Descriptor  0,       (SegCode32Len - 1), (DA_C + DA_32)
LABEL_DESC_VIDEO:   Descriptor  0xB8000,             0xffff, DA_DRW

LABEL_GDT 是段描述符“表”的首地址,LABEL_DESC_CODE32 
是段描述符“表”里面的其
中一个段描述符,LABEL_DESC_VIDEO 
也是段描述符“表”里面的其中一个段描述符。
我的理解对吗?

.set GdtLen, (. - LABEL_GDT)  /* GDT Length */

GdtPtr: .2byte  (GdtLen - 1)  /* GDT Limit */
        .4byte  0             /* GDT Base */

/* GDT Selector */
.set    SelectorCode32, (LABEL_DESC_CODE32 - LABEL_GDT)
.set    SelectorVideo,  (LABEL_DESC_VIDEO  - LABEL_GDT)
SelectorCode32 的值等于 LABEL_DESC_CODE32 距离段首的偏移量。
SelectorVideo的值等于 LABEL_DESC_VIDEO 距离段首的偏移量。
我的理解对吗?

/* Program starts here. */
LABEL_BEGIN:
    mov     %cs, %ax    /* Move code segment address(CS) to data segment */
    mov     %ax, %ds    /* register(DS), ES and SS. Because we have      */
    mov     %ax, %es    /* embedded .data section into .code section in  */
    mov     %ax, %ss    /* the start(metioned in the NOTE above).        */

mov     $0x100, %sp
这句话是什么意思?

    /* Initialize 32-bits code segment descriptor. */
    xor     %eax, %eax
    mov     %cs, %ax
    shl     $4, %eax
addl    $(LABEL_SEG_CODE32), %eax
这是将20位的代码段地址值赋给 LABEL_SEG_CODE32 吗?

    movw    %ax, (LABEL_DESC_CODE32 + 2)
    shr     $16, %eax
    movb    %al, (LABEL_DESC_CODE32 + 4)
    movb    %ah, (LABEL_DESC_CODE32 + 7)
上面4句的意思我始终搞不明白。

    /* Prepared for loading GDTR */
    xor     %eax, %eax
    mov     %ds, %ax
    shl     $4, %eax
    add     $(LABEL_GDT), %eax      /* eax <- gdt base*/
    movl    %eax, (GdtPtr + 2)

    /* Load GDTR(Global Descriptor Table Register) */
lgdtw   GdtPtr
这句话的意思是加载GDT,那是不是说
LABEL_GDT,LABEL_DESC_CODE32,LABEL_DESC_VIDEO的物理地址在这句话执��
�之后才
分配的?如果是的话,那之前将CS,DS等的段地址引入又是如�
��理解?

    /* Clear Interrupt Flags */
    cli

    /* Open A20 line. */
    inb     $0x92, %al
    orb     $0b00000010, %al
    outb    %al, $0x92

    /* Enable protect mode, PE bit of CR0. */
    movl    %cr0, %eax
    orl     $1, %eax
    movl    %eax, %cr0

    /* Mixed-Size Jump. */
    ljmpl $SelectorCode32, $0       /* Thanks to earthengine@gmail, I got */
                                    /* this mixed-size jump insn of gas.  */

LABEL_SEG_CODE32: 
.code32
    mov     $(SelectorVideo), %ax
    mov     %ax, %gs                /* Video segment selector(dest) */

    movl    $((80 * 10 + 0) * 2), %edi
    movb    $0xC, %ah               /* 0000: Black Back 1100: Red Front */
    movb    $'P', %al

    mov     %ax, %gs:(%edi)

    /* Stop here, infinate loop. */
    jmp     .

/* Get the length of 32-bit segment code. */
.set    SegCode32Len, . - LABEL_SEG_CODE32

Original issue reported on code.google.com by linux...@gmail.com on 25 Sep 2008 at 12:34

GoogleCodeExporter commented 9 years ago
......
> /* Global Descriptor Table */
> LABEL_GDT:          Descriptor  0,                        0, 0
> LABEL_DESC_CODE32:  Descriptor  0,       (SegCode32Len - 1), (DA_C + DA_32)
> LABEL_DESC_VIDEO:   Descriptor  0xB8000,             0xffff, DA_DRW
> 
> LABEL_GDT 是段描述符“表”的首地址,LABEL_DESC_CODE32 
是段描述符“表”里面的其
> 中一个段描述符,LABEL_DESC_VIDEO 
也是段描述符“表”里面的其中一个段描述符。
> 我的理解对吗?

对
......
> /* GDT Selector */
> .set    SelectorCode32, (LABEL_DESC_CODE32 - LABEL_GDT)
> .set    SelectorVideo,  (LABEL_DESC_VIDEO  - LABEL_GDT)
> SelectorCode32 的值等于 LABEL_DESC_CODE32 距离段首的偏移量。
> SelectorVideo的值等于 LABEL_DESC_VIDEO 距离段首的偏移量。
> 我的理解对吗?

可以说是对。您可以参考 Fig. 3.12,因为选择子的 0~2 位不是 
index,而段描述符
占 8 个 byte,所以其实 SelectorCode32 的 index 是 1,但由于 1 
在第 3 位
上,所以 SelectorCode32 的内容就是二进制的 1000,就是 8。当 
TI 和 RPL 没有
被定义(均为 0)时,可以将其理解成偏移量,但当 TI 和 RPL 
有定义时,偏移量的理解
就有些不妥,可以将 SelectorCode32 & 0xFFF8 
的结果理解成偏移量。

> mov     $0x100, %sp
> 这句话是什么意思?

将 0x100 给栈指针。

>     /* Initialize 32-bits code segment descriptor. */
>     xor     %eax, %eax
>     mov     %cs, %ax
>     shl     $4, %eax
>     addl    $(LABEL_SEG_CODE32), %eax
> 这是将20位的代码段地址值赋给 LABEL_SEG_CODE32 吗?
>     movw    %ax, (LABEL_DESC_CODE32 + 2)
>     shr     $16, %eax
>     movb    %al, (LABEL_DESC_CODE32 + 4)
>     movb    %ah, (LABEL_DESC_CODE32 + 7)
> 上面4句的意思我始终搞不明白。

请仔细阅读 Fig. 3.2。

>     /* Load GDTR(Global Descriptor Table Register) */
>     lgdtw   GdtPtr
> 这句话的意思是加载GDT,那是不是说
> 
LABEL_GDT,LABEL_DESC_CODE32,LABEL_DESC_VIDEO的物理地址在这句话执��
�之后才
> 
分配的?如果是的话,那之前将CS,DS等的段地址引入又是如�
��理解?

这句话的意思是将 GDT 加载到 GDT 
寄存器中。就像你将代码段加载到 CS 寄存器中一样,代码
段的物理内容是早就定义好的,但是 CPU 
不知道代码段在哪里,需要 CS 寄存器告诉它;同样,
CPU 并不知道 GDT 在哪里,你将 GDT 加载到 GDT 寄存器中,CPU 
就知道到哪里去找段描述符了。

Original comment by solrex on 25 Sep 2008 at 12:56

GoogleCodeExporter commented 9 years ago
谢谢你的回复,但有些地方还是不太明白,也许是我表达的��
�够清楚:
1、
> mov     $0x100, %sp
> 这句话是什么意思?

将 0x100 给栈指针。
-------------------------
%SP好像只有在这里使用,它的作用是什么?

2、
>     /* Initialize 32-bits code segment descriptor. */
>     xor     %eax, %eax
>     mov     %cs, %ax
>     shl     $4, %eax
>     addl    $(LABEL_SEG_CODE32), %eax
> 这是将20位的代码段地址值赋给 LABEL_SEG_CODE32 吗?
>     movw    %ax, (LABEL_DESC_CODE32 + 2)
>     shr     $16, %eax
>     movb    %al, (LABEL_DESC_CODE32 + 4)
>     movb    %ah, (LABEL_DESC_CODE32 + 7)
> 上面4句的意思我始终搞不明白。

请仔细阅读 Fig. 3.2。
-------------------------------------------
重新阅读FIG.3.2,那4句话我明白了。但是这句 “addl    
$(LABEL_SEG_CODE32), %eax”
我还是不太明白。执行这句之前,%EAX里面保存的应该是CS的��
�地址,$(LABEL_SEG_CODE32)是
LABEL_SEG_CODE32 在段内的偏移量吗?如果是的话,这句话“addl  
  $(LABEL_SEG_CODE32),
%eax”的意思是不是把一下代码的入口地址赋给%EAX ?
.....
LABEL_SEG_CODE32: 
.code32
    mov     $(SelectorVideo), %ax
    mov     %ax, %gs                /* Video segment selector(dest) */

    movl    $((80 * 10 + 0) * 2), %edi
    movb    $0xC, %ah               /* 0000: Black Back 1100: Red Front */
    movb    $'P', %al

    mov     %ax, %gs:(%edi)

    /* Stop here, infinate loop. */
    jmp     .
......

Original comment by milanf...@gmail.com on 25 Sep 2008 at 1:26

GoogleCodeExporter commented 9 years ago
>> 将 0x100 给栈指针。
> %SP好像只有在这里使用,它的作用是什么?
那只是在开始一个汇编程序时惯用的对 %SP 
的初始化,在这个例子中是没有用到,只是为了避免
后面可能用到的时候不注意前面没有初始化,覆盖掉有用的��
�据。就像在 C 语言中我们经常写
int main(int argc, char **argv)
但是也经常用不到这两个参数一样。

>> 请仔细阅读 Fig. 3.2。
> 重新阅读FIG.3.2,那4句话我明白了。但是这句 “addl    
$(LABEL_SEG_CODE32), %eax”
> 
我还是不太明白。执行这句之前,%EAX里面保存的应该是CS的��
�地址,$(LABEL_SEG_CODE32)是
> LABEL_SEG_CODE32 
在段内的偏移量吗?如果是的话,这句话“addl    
$(LABEL_SEG_CODE32),
> %eax”的意思是不是把一下代码的入口地址赋给%EAX ?

对。

Original comment by solrex on 25 Sep 2008 at 2:36

GoogleCodeExporter commented 9 years ago

Original comment by solrex on 26 Sep 2008 at 12:16