(莱昂氏unix源代码分析导读-9)系统初启(2)

2.2 main

现在,让我们看看mainC语言代码,我们的老朋友。

1550 main()

1551 {

        ......

1558

1559 updlock = 0;

1560 i = *ka6 + USIZE;                     /iPPDA之后的blockblock

1561 UISD->r[0] = 077406;              /077406,熟悉的数字 4k rw

1562 for(;;) {

1563       UISA->r[0] = i;                 /设置UISA0

1564       if(fuibyte(0) < 0)              /莱昂中将fuibyte的分析留给了读者,这是个很好的练习

                                                         /我的分析在本章的最后,但建议您先自己分析一下

1565                break;

1566       clearseg(i);                        /clear 1block

 

下面详细介绍clearseg——顺便说一下,现在是搞清楚mfpimtpi的时候了。

 

675 .  .globl  _clearseg              

676   _clearseg:

677      mov    PS, -(sp)              /保存PS(压栈)

678      mov    UISA0, -(sp)         /保存UISA0(压栈)

679      mov    $30340,PS            /设置PSCPU优先级7

680      mov    6(sp),UISA0         /参数---->UISA0

681      mov    UISD0, -(sp)        /保存UISD0(压栈)

682      mov    $6, UISD0            /UISD0设置为6rw           

683      clr      r0                           / r0 = 0

684      mov    $32.,r1                 /r1 = 32dec

685   1:

686      clr      -(sp)                /0压栈

687      mtpi    (r0)+               /从当前栈上弹出1 word(值为0)到previous空间r0/向的地址

                                              /1r00,故处在第一个virtual page中,故使用UISA0/进行地址变换; 

                                              /2UISA0设置为参数值;

                                              /3)故,将参数指定的地址清0

688      sob     r1,1b               /循环32次(即1Block长度)

 

689      mov    (sp)+,UISD0         /恢复UISD0

690      mov    (sp)+,UISA0         /恢复UISA0

691      mov    (sp)+,PS                /恢复PS

692      rts     pc                             /return to caller

 

因此, clearseg(i)的执行结果为,将i指向的block0

让我们一鼓作气,顺便把copyseg也解决掉。

695 .  .globl  _copyseg

696   _ copyseg:

697      mov    PS, -(sp)                /保存PS(压栈)

698      mov    UISA0, -(sp)         /保存UISA0(压栈)

699      mov    UISA1, -(sp)         /保存UISA1(压栈)

700      mov    $30340PS 

701      mov    10(sp)UISA0       /这两句是我们的老朋友了:

702      mov    12(SP),UISA1        /  参数1--->UISA0;参数2---->UISA1

703      mov    UISD0, -(sp)         /保存UISD0(压栈)

704      mov    UISD1, -(sp)         /保存UISD1(压栈)

705      mov    $6, UISD0            /UISD0设置为6rw

706      mov    $6, UISD1            /UISD1设置为6rw

707      mov    r2, -(sp)               /保存r

708      clr     r0                           /r00

                                                    /现在,好戏开始了。

709      mov   $8192., r1             /8192.,这个神奇数字是什么意思?

710      mov   $32., r2                 /32.,显然,是block的长度

711  1:

712     mfpi   (r0)+                 /把“前地址空间”的r0地址的内容压栈

713     mtpi   (r1)+                 /从栈中弹出1word到“前地址空间”的r1地址

                                                /完成了将参数1指向word拷贝到了参数2指向的word

714     sob    r2,1b                   /循环32次(1Block长度),结束后就拷贝了整个block

                                

715     mov   (sp)+,r2               /恢复各个寄存器

716     mov   (sp)+,UISD1

717     mov   (sp)+, UISD0

718     mov   (sp)+, UISA1

719     mov   (sp)+, UISA1

720     mov   (sp)+,PS

721     rts     pc                         /return to caller

 

这个神奇的拷贝过程是怎么发生的?

(1)   首先,要先搞清8192这个神奇数字——它是一个page的长度,同时也是第二个virtual page 的起始地址!

(2)   首次执行mfpi  (r0)+时,r00,是第一个virtual page的起始地址!

             物理地址=UISA0*64+0——会将该地址的内容压栈;

(3)   mtpi   (r1)+,而r1为第二个virtual page的起始地址,它指向的物理地址为“物理地址= UISA1*64+0”。这条语句

             会将栈内的内容(UISA0*64+0的内容)弹出到该物理地址上;

(4)   执行32次后,就拷贝了整个block

 

UISA0UISA1分别由两个参数设置,所以,copyseg的作用就是将参数1指向的block的内容拷贝到参数2指向的block

【注】:mfpi mtpi是“fuibyte”的难点所在。如果“fuibyte”一直使您迷惑的话,现在是解决它的时候了。
               您最好独立完成这个习题,我的分析在本章的最后,但希望您在完成自己的分析之前不要去看它。

 

1567       maxmem++;             /可用memory大小

1568       mfree(coremap, 1, i);      /扩充可用memory

1569       i++;

1570 }

 

这个无限for循环会从PPDA后的第一个block开始,一直Loop到物理内存的尽头,将可用内存block通过mfree回收到可用内存表中。

 

1571 if(cputype == 70)                              /1461  _cputype:40

1572      for(i=0; i<62; i=+2) {                   /故,此段代码不会被执行到,跳过不看

1573           UBMAP->r[i] = i<<12;

1574           UBMAP->r[i+1] = 0;

1575      }

                   ……

1595 /*

1596 * determine clock

1597 */

1598

1599 UISA->r[7] = ka6[1]; /* io segment */           /陷阱!

                                                                               /ka6[1]指向最后一个 pageka6[0]才是第7page

1600 UISD->r[7] = 077406;

1601 lks = CLOCK1;

1602 if(fuiword(lks) == -1) {                                 /获取时钟设备,书中有详细注解

1603       lks = CLOCK2;

1604       if(fuiword(lks) == -1)  

1605               panic("no clock");  

1606 }

1607 *lks = 0115;

1608

 

博客地址:http://blog.csdn.net/cszhao1980

 

你可能感兴趣的:(c,IO,unix,语言,代码分析)