question1:
这道题主要涉及到的set指令,具体的set指令可以参考:
table3
当然,这里还涉及到之前的知识点:
table4
因此,就可以得出:
1、<
2、(unsigned) <
3、(short) (short) >=
4、(char) (char) !=
5、>
6、>
要点一:
c语言里有一个经典的操作:循环,那么在操作系统里,主要表现为:do-while循环。
do-while的通用形式是这样的:
do
body-statement
while(test-expr)
即当test-expr非零,就会继续循环。
当然,在学校安排的汇编实验中,还可以碰到以下的形式:
loop:
body-statement
t=test-expr;
if (t)
goto loop;
除了do-while循环,还有while循环,通用形式和c语言类似(我觉得):
while(test-expr)
body-statement
这和之前的不同之处在于,在循环的第一次,while循环就可以ban了这个循环。do-while有变体,while肯定也是有的:
loop:
t=test-expr
if (!t)
goto done;
body-statement
goto loop;
done;
c编译器大部分都是do-while循环,用一个条件分支来在需要时省略循环体的第一次执行:
if (!test-expr)
goto done;
do
body-statement
while (test-expr);
done;
变体是:
t = test-expr;
if (!t)
goto done;
loop:
body-statement
t = test-expr;
if (t)
goto loop;
done;
要点二:
关于call指令:
call
...
leave
ret
那么,上题:
可以看到,这个只有call,么有ret,所以并不是一个真正的过程调用。
A:%eax被设置成 popl 指令的地址
B:因为这不俗一个真正的子过程调用,因为控制是和指令相同的顺序进行,返回值是从栈中弹出的。
C:将程序计数器的值放到整数寄存器中的唯一方法。
question2
答:前三个寄存器是被调用者保存的,因此会影响到调用者的行为,必须将它们保存在栈中,再返回之前要恢复它们;后三个寄存器是调用者保存的,改变它们把那个不会影响到调用者的行为。
要点二:
那么数组的分配和访问也是比较简单的,数组有以下形式:
char A[12];
char *B[8];
double C[6];
double *D[5];
那么就会有:
| 数组 | 元素大小 | 总大小 | 起始地址 | 元素i |
| A | 1 | 12 | XA | XA+i |
| B | 4 | 32 | XB | XB+4i |
| C | 8 | 48 | XC | XC+8i |
| D | 4 | 20 | XD | XD+4i |
question3:
| 表达式 | 类型 | 值 | 汇编代码 |
| S+1 | short * | Xs+2 | leal 2(%edx) , %eax |
| S[3] | short | M[Xs+6] | movw 6(%edx) , %eax |
| &S[I] | short * | Xs+2i | leal (%edx,%ecx,2),%eax |
| S[4*i+1] | short | M[Xs+8i+2] | movw 2(%edx,%ecx,8) , %eax |
| S+i-5 | short * | Xs+2i-5 | leal -10(%edx , %ecx , 2) , %eax |



