Patt&Patel-“Introduction to Computing Systems“(2)期末样卷题目解析

就自己写的解析吧,唉。各个知识点见诸小标题。

Assembly Language

Patt&Patel-“Introduction to Computing Systems“(2)期末样卷题目解析_第1张图片

题干已经说了“LABEL and LATER appear somewhere in the program”。

SEQUENCE1,LD R1,LABEL当然是R1<-mem[LABEL];

SEQUENCE 2,LD R0,OTHER相当于R0<-mem[OTHER],即R0<-LABEL然后LDR R1,R0 #0相当于R1<-men[LABEL]。

那么为什么前者有时还会无法运行呢?

让我们试着在LC3模拟器上跑下SEQUENCE1。

(网页链接是这个 WebLC3 Simulator (umanitoba.ca))

Patt&Patel-“Introduction to Computing Systems“(2)期末样卷题目解析_第2张图片

 如这段代码所示,我们把LABEL放在比较靠前的位置,而在编译后,我们可以看到在PC的位置是0x3003,其实也很好理解,因为一开始设置的PC是.ORIG x3000,第一条命令LD R1,LABEL就处在这个位置,然后是判断是否循环的BRnzp LATER在x3001,然后是中断程序运行的HALT在x3002,然后就轮到LABEL了,落在PC的x3003上。

Patt&Patel-“Introduction to Computing Systems“(2)期末样卷题目解析_第3张图片

step in一次后(PC+1,就是相当于只执行下一步),可以发现已经把xFE00寄存到R1里了。可以看到左边的register表,程序是没有出现异常的。

Patt&Patel-“Introduction to Computing Systems“(2)期末样卷题目解析_第4张图片

那么 LD到底是如何运作的呢?

Patt&Patel-“Introduction to Computing Systems“(2)期末样卷题目解析_第5张图片

结合上例来说明的话就是,当运行LD R1,LABEL时,PC是x3000,而我们的LABEL的PC是x3003,结合十六进制,0011 0000 0000 0011,后九位是0 0000 0011,然后SEXT,就是extend(延伸到16位),变回0000 0000 0000 0011,也就是x0003,也就是加3,也就是mem(LABEL)。如果要去进一步问上述的过程是如何完成的,就要回到我们的这张图:

Patt&Patel-“Introduction to Computing Systems“(2)期末样卷题目解析_第6张图片

 但是我们在考虑问题的时候并不是拿这张图去考虑的(如上图的[8:0]SEXT),这就体现出abstraction of layers的主题了,但是,这样的物理结构决定了当LABEL处于比较后的位置时,比如我们取一个极端的xFFFF,也就是x 1111 1111 1111 1111,后九位是x 1 1111 1111,但是前面的7位它是补0的,最后也就是x 0000 0001 1111 1111,那么这种情况下就没办法正确地像之前的那种情况到达这个位置了。还是设置ORIG位x3000的情况,即,x 0011 0000 0000 0000加上这段,也就变成了x 0011 0001 1111 1111,但是我们的数据是存在x 1111 1111 1111 1111,也就是答案说的“LABEL may be too far away”。

SEQUENCE 2看起来和我们在上面写的SEQUENCE 1的特殊情况很像,但还是有区别,因为多使用了一个register,这个register其实就解决了如果LABEL放在很远位置的问题。我相信聪明的诸位肯定可以想明白这点的。

主要还是想借这个例子来说明“abstraction of layers”和“think both softwarely and hardwarely”。

C++のLC-3 stack

Patt&Patel-“Introduction to Computing Systems“(2)期末样卷题目解析_第7张图片

基础知识:Allocating Space for Variables

There are two regions of memory in which C variables are allocated storage: the global data section and the run-time stack. The global data section is where all global variables are stored. More generally, it is where variables of the static storage class are allocated. The run-time stack is where local variables (of the default automatic storage class) are allocated storage.

All local variables for a function are allocated in a "memory template" called an avtivation record or stack frame. An activation record is a region of contiguous memory locations that contains all the local variables for a given function. Every function has an activation record (or more precisely, every invocation of a function has an activation record--more on this later).

Whenever we are executing a particular function, the highest memory address of the activation record will be stored in R5--R5 is called the frame pointer

Whenever we call a function in C, the activation record for the function is pushed on to the run-time stack. That is, the function's activation record is allocated on top of the stack. R5 is appropriately adjusted to point to the base of the record--therefore any code within the function that accesses local variables will now work correctly. Whenever the function completes and control is about to return to the caller, the activation record is popped off the stack. R5 is adjusted to point to the caller's activation record. Throughout all of this, R6 always contains the address of the top of the run-time stack--it is called the stack pointer.

批注:

  1. 只要记着R6 always contains the address of the top of the run-time stack,就可以知道R6的位置了。
  2. base应该指的是最底层。我们知道stack是自下而上的,所以base的位置是在底部,这也帮助我们理解为什么叫做frame pointer,体现了base吧。也因此当完成这个activation record移到下一个activation record的时候,其实相当于移到了下一个frame的底部吧,而写一个frame的底部就是local variable的地址。

另一个可以参考的图是这个: 

Patt&Patel-“Introduction to Computing Systems“(2)期末样卷题目解析_第8张图片

下面结合一个具体的例子来看。 

类似的例子

这个例子是输入10个整数,然后计算这10个整数的平均数,C语言的代码是:

#include
#define MAX_NUMS 10

int Average(int input_values[]);

int main()
{
    int index;             /* Loop iteration variable */
    int mean;              /* Average of numbers      */
    int numbers[MAX_NUMS]; /* Original input numbers  */
    
    /*Get input*/
    printf("Enter %d numbers.\n", MAX_NUMS);
    for(index = 0; index < MAX_NUMS; index++){
        printf("Input number %d: ",index);
        scanf("%d",&numbers[index]);
    }
    mean = Average(numbers);

    printf("The average of these numbers is %d\n", mean);

}

int Average(int inputvalues[])
{
    int index;
    int sum = 0;

    for(index = 0; index < MAX_NUMS; index++){
        sum = sum + inputValues[index];

    }
    return(sum/MAX_NUMS);   
}

Patt&Patel-“Introduction to Computing Systems“(2)期末样卷题目解析_第9张图片

这里我想到的第一个问题是,既然stack是先入的后出,那么为什么从上到下是numbers[0]到numbers[10]而不是从numbers[10]到numbers[0],这是因为我们看到main函数先定义了index,然后是mean,最后是numbers[MAX_NUMS]这个array,如果我们把这一个array当成一个整体就好理解了,并不与stack的“先入的后出”矛盾。

写的时候先把解析写了(然后回过头来看这个就很简单了),相信聪明的大家一定可以看明白的~(主要是我懒)。

解析

Patt&Patel-“Introduction to Computing Systems“(2)期末样卷题目解析_第10张图片

首先传入func的参数有s和skip,所以放在栈的最底端(至于s和skip的先后顺序有没有要求我不是很清楚,如果是按照答案的话,应该是先传入skip,后传入s)。至于this,我理解的是指向这个函数的指针。

根据“ Whenever the function completes and control is about to return to the caller, the activation record is popped off the stack.”可知需要linkage满足这样一个需求。

最后就是f(可以理解为终于到这个函数内部了),所以f位于最上方。

R6,R5的位置的话,因为R6 always contains the address of the top of run-time stack,所以指向f的地址,R5的话在previous frame pointer的上方。

你可能感兴趣的:(大学课程,c语言,学习,笔记,其他)