2.2 main
现在,让我们看看main。C语言代码,我们的老朋友。
1550 main()
1551 {
......
1558
1559 updlock = 0;
1560 i = *ka6 + USIZE; /i为PPDA之后的block的block号
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 1个block
下面详细介绍clearseg——顺便说一下,现在是搞清楚mfpi和mtpi的时候了。
675 . .globl _clearseg
676 _clearseg:
677 mov PS, -(sp) /保存PS(压栈)
678 mov UISA0, -(sp) /保存UISA0(压栈)
679 mov $30340,PS /设置PS(CPU优先级7)
680 mov 6(sp),UISA0 /参数---->UISA0
681 mov UISD0, -(sp) /保存UISD0(压栈)
682 mov $6, UISD0 /UISD0设置为6(r、w)
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指/向的地址
/(1)r0为0,故处在第一个virtual page中,故使用UISA0/进行地址变换;
/(2)UISA0设置为参数值;
/(3)故,将参数指定的地址清0
688 sob r1,1b /循环32次(即1个Block长度)
689 mov (sp)+,UISD0 /恢复UISD0
690 mov (sp)+,UISA0 /恢复UISA0
691 mov (sp)+,PS /恢复PS
692 rts pc /return to caller
因此, clearseg(i)的执行结果为,将i指向的block清0。
让我们一鼓作气,顺便把copyseg也解决掉。
695 . .globl _copyseg
696 _ copyseg:
697 mov PS, -(sp) /保存PS(压栈)
698 mov UISA0, -(sp) /保存UISA0(压栈)
699 mov UISA1, -(sp) /保存UISA1(压栈)
700 mov $30340,PS
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设置为6(r、w)
706 mov $6, UISD1 /UISD1设置为6(r、w)
707 mov r2, -(sp) /保存r
708 clr r0 /r0清0
/现在,好戏开始了。
709 mov $8192., r1 /8192.,这个神奇数字是什么意思?
710 mov $32., r2 /32.,显然,是block的长度
711 1:
712 mfpi (r0)+ /把“前地址空间”的r0地址的内容压栈
713 mtpi (r1)+ /从栈中弹出1个word到“前地址空间”的r1地址
/完成了将参数1指向word拷贝到了参数2指向的word
714 sob r2,1b /循环32次(1个Block长度),结束后就拷贝了整个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)+时,r0为0,是第一个virtual page的起始地址!
物理地址=UISA0*64+0——会将该地址的内容压栈;
(3) mtpi (r1)+,而r1为第二个virtual page的起始地址,它指向的物理地址为“物理地址= UISA1*64+0”。这条语句
会将栈内的内容(UISA0*64+0的内容)弹出到该物理地址上;
(4) 执行32次后,就拷贝了整个block。
UISA0、UISA1分别由两个参数设置,所以,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]指向最后一个 page,ka6[0]才是第7个page
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