-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathex9.trace.0.txt
More file actions
91 lines (90 loc) · 5.52 KB
/
ex9.trace.0.txt
File metadata and controls
91 lines (90 loc) · 5.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
⭐⭐⭐ 考试内容,务必理解
栈帧下标从0开始
|
v
[ ]{0: INCSP 1} // int t; 没有使用的全局变量
[ 0 ]{2: LDARGS} // main 命令行参数 i = 0【传入i为0】
[ 0 0 ]{3: CALL 1 7} // 调用位于7的main(0)函数,参数1个
↑ // [6 -999 0]:
命令行参数 // CALL 1 7拿掉栈上1个参数 0
// 把返回地址6压入栈
⭐返回地址计算:3 4 5是call的指令,返回地址是call的下一个地址即6,
因为直接调用main,所以7开始就是main的函数体的内容
// 参数i=0 old bp: -999 默认初始bp值为-999
旧bp
↓ 参数i
↓ ↓
[ 0 6 -999 0 ]{7: INCSP 1} // 给int r分配空间
下标1的位置:返回地址6 下标2的位置:bp默认值
INCSP 1分配一个空间,把r的默认值0(因为没有赋初值)压入栈顶
r
[ 0 6 -999 0 0 ]{9: GETBP} // 获得基指针bp = 3,把3压入栈顶
[ 0 6 -999 0 0 3 ]{10: CSTI 0} //int类型0压入栈顶 bp + 0即main参数i的位置
[ 0 6 -999 0 0 3 0 ]{12: ADD} //拿掉3和0,计算3+0=3,结果3压入栈顶,表示参数i的地址
&i
[ 0 6 -999 0 0 3 ]{13: LDI} //获取下标3的值,即i=0
s[sp] = s[s[sp]]; 因为sp=5,所以s[5]=s[s[5]]=s[3]=0
i
[ 0 6 -999 0 0 0 ]{14: GETBP} 获得bp=3
[ 0 6 -999 0 0 0 3 ]{15: CSTI 1} bp+1 获得main局部变量r的位置
[ 0 6 -999 0 0 0 3 1 ]{17: ADD} 拿掉3和1,计算结果3+1=4,即&r=4压入栈顶
i &r
[ 0 6 -999 0 0 0 4 ]{18: CALL 2 35} //调用位于35的fac(0,4)
4是&r
// CALL 2 35 拿掉栈上的两个参数 0 4
// 返回地址 = 21,oldbp = 3
⭐返回地址计算:18 19 20是call的指令,返回地址是call的下一个地址即21,
因为调用fac后还要执行print,所以22-34是print的相关操作,35开始是fac的函数体的内容
返回地址ra
| oldbp
| |
v v n &r
[ 0 6 -999 0 0 21 3 0 4 ]{35: GETBP} // fac(0,4)函数开始执行, 0 4为参数, bp指向第1个参数i=0的位置
ra和olddp是CALL指令先把i和&r,然后放入返回地址和旧dp
bp
↓
n &r = res
↓ ↓ bp
[ 0 6 -999 0 0 21 3 0 4 7 ]{36: CSTI 0} dp=7,GETBP把7入栈
[ 0 6 -999 0 0 21 3 0 4 7 0 ]{38: ADD} bp+0为fac参数n
[ 0 6 -999 0 0 21 3 0 4 7 ]{39: LDI} //获取下标7的值,即fac参数n=0
[ 0 6 -999 0 0 21 3 0 4 0 ]{40: CSTI 0} 0入栈
[ 0 6 -999 0 0 21 3 0 4 0 0 ]{42: EQ} // 比较n是否等于0
[ 0 6 -999 0 0 21 3 0 4 1 ]{43: IFZERO 57} // 相等继续执行45,不相等跳转57。执行IFZERO后sp-1
[ 0 6 -999 0 0 21 3 0 4 ]{45: GETBP} //bp=7入栈
[ 0 6 -999 0 0 21 3 0 4 7 ]{46: CSTI 1} //1入栈
[ 0 6 -999 0 0 21 3 0 4 7 1 ]{48: ADD} //bp+1=8,fac参数res地址
res &res //res是指针指针本身的地址 &res 是 8
| | //指针res的值 是r的地址,&r = 4
v v //指针res的内容 *res是r的值,r = 0
[ 0 6 -999 0 0 21 3 0 4 8 ]{49: LDI} // *res的左值 = 4
获取下标8的值,即res=4
[ 0 6 -999 0 0 21 3 0 4 4 ]{50: CSTI 1} 1入栈
*res n &r = res
| | |
v v v
[ 0 6 -999 0 0 21 3 0 4 4 1 ]{52: STI} //当前sp在下标10,s[sp-1]=4,把下标4的值赋为1,并把sp-1的位置赋为1
↑ // *res = 1.赋值完成后,该值保留在栈上。STI结束后,sp--
*res的值
*res
|
v
[ 0 6 -999 0 1 21 3 0 4 1 ]{53: INCSP -1} //释放空间,丢弃栈顶*res值=1
^^^
[ 0 6 -999 0 1 21 3 0 4 ]{55: GOTO 97} 无条件跳转
[ 0 6 -999 0 1 21 3 0 4 ]{97: INCSP 0} //fac无局部变量.空操作
[ 0 6 -999 0 1 21 3 0 4 ]{99: RET 1} //从fac(0,4)返回,撤销栈帧 return; RET m-1 //fac参数个数 m=2
res=s[8]=4 sp=8-1=7 bp=s[6]=3 pc=s[5]=21 s[5]=4
[ 0 6 -999 0 1 4 ]{21: INCSP -1} // fac(0); 丢弃 fac(0);的值
fac(0)=4 set到返回地址上
[ 0 6 -999 0 1 ]{23: GETBP} bp=3,3入栈
[ 0 6 -999 0 1 3 ]{24: CSTI 1} 1入栈
[ 0 6 -999 0 1 3 1 ]{26: ADD} //bp+1=4,得到r的偏移地址
[ 0 6 -999 0 1 4 ]{27: LDI} //获取下标4的值,即main中r=1
[ 0 6 -999 0 1 1 ]{28: PRINTI} //输出r
1 [ 0 6 -999 0 1 1 ]{29: INCSP -1} //释放空间,丢弃PRINTI的值(r值)=1
[ 0 6 -999 0 1 ]{31: INCSP -1} //释放空间,丢弃main的局部变量r=1
[ 0 6 -999 0 ]{33: RET 0} // 从main(0) 中 return; RET m-1
// main 参数个数 m=1
res=s[3]=0 sp=3-1=2 bp=s[2]=-999 pc=s[1]=6 s[1]=0
[ 0 0 ]{6: STOP} // 执行结束