3.61
题中代码在循环时会产生6个临时的变量,故共需要六个寄存器在存放数据,但是由于处理器的六个寄存器中,%esp和%ebp不能用于存放临时数据,而且另外一个寄存器还必须用来保存乘法指令的结果。因此必须将循环中的值的数量减少到5个。
当没有足够多的寄存器来保存临时数据时,编译器必须把一些局部变量放到存储器中
由于在每次循环中代码从存储器中取出N的值进行检查循环是否终止,所以我觉得可以去掉每次的减产环节,直接用立即数来控制循环结束。代码如下:
int var_prod_ele(int n, int A[n][n], int B[n][n], int i, int k) { int j = n-1; int result = 0; for(; j!=-1; --j) result += A[i][j] * B[j][k]; return result; }
但是这样得到的结果仍然会使用到存储器。
按下面的代码,循环里面貌似就没有用到存储器。
但是用到了一个常量4,就是增加a的时候,会add 4。
只需要result,a,e,b,4n这五个变量。
思路如下,先初始化A数组的行和B数组的列,记住他们的地址,同时记住A数组那一行最后一个元素的地址,之后循环每次用变换的A数组行地址和A数组最后一个元素地址进行比较来控制循环的结束。若没有到达A数组行的最后一个元素,则A数组依次向后移动,B数组依次向下移动,直到最后达到最后一个元素。代码如下:
int var_prod_ele(int n, int A[n][n], int B[n][n], int i, int k) { int result = 0; int *a = &A[i][0]; int *b = &B[0][k]; int *e = &A[i][n]; for(;a!=e;) { result += *a * *b; b+=n; a++; } return result; }
3.63
E1和E2是用#define声明的宏表达式,用参数表示A矩阵的维度。
int sum_col(int n, int A[E1(n)][E2(n)],int j) {
int i;
int result = 0;
for (i = 0; i < E1(n); i++)
result += A[i][j];
return result;
}
1.分析通过信息交换所得的观察。
最常用于协议逆向工程,涉及使用总线分析器和数据包嗅探器。在接入计算机总线或网络的连接,并成功截取通信数据后,可以对总线或网络行为进行分析,以制造出拥有相同行为的通信实现。此法特别适用于设备驱动程序的逆向工程。有时,由硬件制造商特意所做的工具,如JTAG端口或各种调试工具,也有助于嵌入式系统的逆向工程。对于微软的Windows系统,受欢迎的底层调试器有SoftICE。
2.反汇编,即使用反汇编器,把程序的原始机器码,翻译成较便于阅读理解的汇编代码。这适用于任何的计算机程序,对不熟悉机器码的人特别有用。流行的相关工具有OllyDebug和IDA。
3.反编译,即使用反编译器,尝试从程序的机器码或字节码,重现高级语言形式的源代码。
E1(n)在esi中,esi = 3n。
E2(n)在ebx中,ebx = 4*E2(n) = 4*(2n-1)。
所以E2(n) = 2n-1。