-4
input a number and store it in x
input a number and store it in y
while x < 10 do
x =x +1 
 output value of x;
end while
output the value of y*2
4

1 回答 1

2

While 语句使用 if-goto-label 转换为汇编语言。我们可以用 C 来说明:

while ( x < 10 ) {
    x++;
    print(x);
}
...

变成:

loop1:
    if ( x >= 10 ) goto loop1Done;    // this is a conditional branch
    x++;
    print(x);
    goto loop1;                       // this is an unconditional branch
loop1Done:
    ...

请注意,在 if-goto-label 样式中,条件x < 10反转为x >= 10b/c 我们希望在此条件下退出循环,而 Cwhile语句告诉我们何时继续循环。因为这两种意义(C whilevs. C if-goto-label)是相反的,所以我们选择 的否定x < 10,即x >= 10退出循环。


对应于 C 的 goto 语句,MARIE 使用Jump汇编指令进行无条件分支。

对应于 C 的 if-goto 结构,MARIE 使用条件跳转进行条件分支:该Skipcond指令用于多指令序列中。

将累加器寄存器 与 0Skipcond进行比较AC,要么允许执行下一条指令,要么跳过并跳过它——当它跳过时,它正好跳过 1 条指令:不多也不少。通常下一条指令Jump用于更改控制流程(它不一定是跳转,它可以是您想要有条件地跳过的任何其他单条指令)。

为了完成条件分支(if-goto),我们将条件跳转指令 ,Skipcond与无条件分支指令 ,结合起来Jump。因为我们告诉Skipcond何时跳过,它只会在不跳过时分支。因此,我们从 if-goto-label 形式中否定条件:Skipcond

if ( x >= 10 ) goto loop1Done;

变成:

Skipcond 000                 // Skip the Jump if AC < 0
Jump loop1Done               // Jump may or may not fire, depending on prior Skip

对于更大范围的示例,请使用以下语句:

if ( x >= 10 ) goto loop1Done;

因为跳过/跳转序列使我们从 if-goto-label 形式中取反(第二次,如果你从 C 开始),我们想要x < 10Skipcond; Jump序列中设置。

首先我们应用一些基本的数学运算:x - 10 < 0,从关系运算符的两边减去 10 <,保留x < 10 (modulo overflow)的逻辑。现在我们有了一个比较为零的表达式,这适合 MARIESkipcond可以为我们做的事情。

loop1,                
       // if ( x >= 10 ) goto loop1Done;
       load X         // AC = x
       Subt Ten       // AC = x - 10
       Skipcond 000   // MARIE will skip the next instruction if AC < 0, i.e. x < 10
       Jump loop1Done // Will only fire if AC >= 0, i.e. x >= 10

       // x++;
       Load X         // AC = x
       Add One        // AC = x + 1
       Store X        // x = AC

       Output         // outputs the AC (note that the AC == x here)

       Jump loop1     // continue the loop
loop1Done,            // end of loop, on to next statement after
        ...

        // Variables & Constants
X,      Hex 0
Ten,    Dec 10
One,    Dec 1

总之,我们可以使用 if-goto、goto 和标签将任何控制结构从结构化语句形式转换为汇编形式。即使结构化语句是嵌套的(嵌套不会改变替换模式),结构化语句也使用此类模式进行字面翻译。

在 MARIE 上,我们可以从一对 skipcond/jump 指令组成 if-goto 操作。为了使用 skipcond/jump 对,我们需要计算一个相对于 0 的值到 AC 中(即x-10)。


MARIE 上的复杂问题,Skipcond不具有所有通用关系:<, <=, ==, !=, >=, >. MARIE 只有<, ==, 和>— 它们不能在一条指令中组合成<=or >=

有时我们需要使用Skipcond不会直接为我们执行的关系运算符之一执行 if-goto(所以,是的,我们可以再次反转条件)。

首先,让我们看看在 if-goto-label 中使用相反条件的通用方法:

    if ( x >= 10 ) goto label1;         // goes to label1 if x >= 10
    ...                                 // comes here otherwise, i.e. x < 10

    if ( x < 10 ) goto uniqueNewlabel;  // goes to uniqueNewLabel if x < 10
    goto label1;                        // goes here (which jumps to label1) if x >= 10
uniqueNewlabel:                         // comes here if x < 10

上面的后者将原始 if-goto 中<的关系替换为关系的使用,以完成相同的控制流逻辑。>=顺便说一句,这种转换也可以反过来起作用,所以如果你有后者,它可以转换成前者。

好的,现在我们有了一个方法来反转我们需要的操作,我们可以将它应用到 MARIE 的Skipcond序列中。假设我们确实需要以下内容:

    if ( x < 10 ) goto somewhere;

在 MARIE 的假设变体中,这可能转化为

    Skipcond >=           // skips the succeeding Jump on >=
    Jump somewhere        // goes here on <, so executes the Jump

但是没有 Skipcond for >=。我们将使用上述模式替换来反转>=<MARIE 确实具有的:

    Skipcond 000             // < that MARIE does have
    Jump uniqueNewLabel      // fires only when >=, so used to "skip" the next line
    Jump somewhere           // desired target for when <
uniqueNewLabel,

还有其他模式可以改变测试的感觉。

    if ( x < 10 ) goto somewhere;

在逻辑上等价于(在整数上):

    if ( x <= 9 ) goto somewhere;

<交换了for 的使用后<=,我们可以再次使用 MARIE 的 Skipcond/Jump 两个指令对来处理这个 if-goto。

于 2021-03-02T17:29:31.110 回答