-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathex9.trace.3.txt
218 lines (201 loc) · 11.1 KB
/
ex9.trace.3.txt
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
栈帧下标从0开始
|
v
[ ]{0: INCSP 1} int t;
[ 0 ]{2: LDARGS}
[ 0 3 ]{3: CALL 1 7}
[ 0 6 -999 3 ]{7: INCSP 1} //int r;
[ 0 6 -999 3 0 ]{9: GETBP}
[ 0 6 -999 3 0 3 ]{10: CSTI 0}
[ 0 6 -999 3 0 3 0 ]{12: ADD}
[ 0 6 -999 3 0 3 ]{13: LDI} // fac i
[ 0 6 -999 3 0 3 ]{14: GETBP}
[ 0 6 -999 3 0 3 3 ]{15: CSTI 1}
[ 0 6 -999 3 0 3 3 1 ]{17: ADD} // fac &r
[ 0 6 -999 3 0 3 4 ]{18: CALL 2 35} // call fac 3
[ 0 6 -999 3 0 21 3 3 4 ]{35: GETBP} // retaddr:21, oldbp:3, i:3, &r:4
^ ^
oldbp bp-1的内容为oldbp的地址,bp自己的位置为7
[ 0 6 -999 3 0 21 3 3 4 7 ]{36: CSTI 0}
[ 0 6 -999 3 0 21 3 3 4 7 0 ]{38: ADD}
[ 0 6 -999 3 0 21 3 3 4 7 ]{39: LDI} // fac n=3
[ 0 6 -999 3 0 21 3 3 4 3 ]{40: CSTI 0}
[ 0 6 -999 3 0 21 3 3 4 3 0 ]{42: EQ} // EQ 将 n = 0? 返回到栈上 0 为false
[ 0 6 -999 3 0 21 3 3 4 0 ]{43: IFZERO 57} //if false goto 57 if语句的 else分支
[ 0 6 -999 3 0 21 3 3 4 ]{57: INCSP 1} // n != 0 int temp;
[ 0 6 -999 3 0 21 3 3 4 0 ]{59: GETBP} // bp+0 <-- &n
^^^
变量temp的位置:9
[ 0 6 -999 3 0 21 3 3 4 0 7 ]{60: CSTI 0}
[ 0 6 -999 3 0 21 3 3 4 0 7 0 ]{62: ADD}
[ 0 6 -999 3 0 21 3 3 4 0 7 ]{63: LDI} // n = 3 入栈
[ 0 6 -999 3 0 21 3 3 4 0 3 ]{64: CSTI 1}
[ 0 6 -999 3 0 21 3 3 4 0 3 1 ]{66: SUB} //n = n - 1 ==> 2
[ 0 6 -999 3 0 21 3 3 4 0 2 ]{67: GETBP} //bp + 2 <-- &temp
[ 0 6 -999 3 0 21 3 3 4 0 2 7 ]{68: CSTI 2}
[ 0 6 -999 3 0 21 3 3 4 0 2 7 2 ]{70: ADD} //&temp 入栈 ==>9
^^^
变量temp的位置:9
[ 0 6 -999 3 0 21 3 3 4 0 2 9 ]{71: CALL 2 35} // call fac(n=2,&temp=9) 9 <== &temp
// 返回地址 74 <-- *res = tmp * n;
oldbp :7
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 ]{35: GETBP} //35: fac n =2 入口
^ ^
oldbp bp-1的内容为oldbp的地址7
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 12 ]{36: CSTI 0}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 12 0 ]{38: ADD}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 12 ]{39: LDI} 从栈帧上 加载 n = 2
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 2 ]{40: CSTI 0}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 2 0 ]{42: EQ}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 ]{43: IFZERO 57} n = 0? false 转 57
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 ]{57: INCSP 1} //分配 int temp;
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 ]{59: GETBP}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 12 ]{60: CSTI 0}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 12 0 ]{62: ADD}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 12 ]{63: LDI}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 2 ]{64: CSTI 1}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 2 1 ]{66: SUB}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 1 ]{67: GETBP}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 1 12 ]{68: CSTI 2}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 1 12 2 ]{70: ADD}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 1 14 ]{71: CALL 2 35} // fac(n=1,&temp=14) call m = 2
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 ]{35: GETBP}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 17 ]{36: CSTI 0}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 17 0 ]{38: ADD}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 17 ]{39: LDI}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 ]{40: CSTI 0}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 0 ]{42: EQ}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 ]{43: IFZERO 57}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 ]{57: INCSP 1} // 分配int temp;
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 ]{59: GETBP}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 17 ]{60: CSTI 0}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 17 0 ]{62: ADD}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 17 ]{63: LDI}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 1 ]{64: CSTI 1}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 1 1 ]{66: SUB}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 0 ]{67: GETBP}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 0 17 ]{68: CSTI 2}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 0 17 2 ]{70: ADD}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 0 19 ]{71: CALL 2 35}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 74 17 0 19 ]{35: GETBP}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 74 17 0 19 22 ]{36: CSTI 0}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 74 17 0 19 22 0 ]{38: ADD}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 74 17 0 19 22 ]{39: LDI}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 74 17 0 19 0 ]{40: CSTI 0}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 74 17 0 19 0 0 ]{42: EQ}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 74 17 0 19 1 ]{43: IFZERO 57} // n = 0?
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 74 17 0 19 ]{45: GETBP} // if n = 0 true
^
bp自己的位置为22
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 74 17 0 19 22 ]{46: CSTI 1} // (bp + 1) => &res
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 74 17 0 19 22 1 ]{48: ADD}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 74 17 0 19 23 ]{49: LDI} // 从栈帧上加载 &res => 19
^^^
&res
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 74 17 0 19 19 ]{50: CSTI 1}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 0 74 17 0 19 19 1 ]{52: STI} // *res = 1
^^^
*res
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 74 17 0 19 1 ]{53: INCSP -1} // *res=1; 赋值语句丢弃语句值
^^^
*res
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 74 17 0 19 ]{55: GOTO 97} // 转 fac(0) 出口
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 74 17 0 19 ]{97: INCSP 0}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 74 17 0 19 ]{99: RET 1} // fac 是void调用, ret m-1 返回到fac(1) else分支
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 19 ]{74: INCSP -1} // fac (1)中 else分支 函数调用值丢弃 fac(0);
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 ]{76: GETBP} (bp+1) ==> &res
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 17 ]{77: CSTI 1}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 17 1 ]{79: ADD}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 18 ]{80: LDI} &res = 14 fac(n=1,&res=14)返回值的地址
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 14 ]{81: GETBP} (bp + 2) ==> temp = 1
^^^
&res 后面 赋值 的STI需要用到
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 14 17 ]{82: CSTI 2}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 14 17 2 ]{84: ADD}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 14 19 ]{85: LDI} temp = 1
^^^
temp 就是 fac(0)中的 *res
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 14 1 ]{86: GETBP}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 14 1 17 ]{87: CSTI 0}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 14 1 17 0 ]{89: ADD}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 14 1 17 ]{90: LDI} (bp+0) ==> n = 1 fac(1)中
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 14 1 1 ]{91: MUL} temp * n ==> 1 * 1
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 0 74 12 1 14 1 14 1 ]{92: STI} *res = tmp * n 值为1
^^^
&res = 14
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 74 12 1 14 1 1 ]{93: INCSP -1} // *res = temp * n; 丢弃赋值语句的值
^^^
*res = temp * n
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 74 12 1 14 1 ]{95: INCSP -1} //释放 int temp; fac(n=0,&res=19)
^^^
fac(0) 中 的&res是fac(1)中分配的temp位置
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 74 12 1 14 ]{97: INCSP 0} // fac(1) 无局部变量
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 74 12 1 14 ]{99: RET 1} // void fac(1) ret 2-1 返回到fac(2)
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 14 ]{74: INCSP -1} fac(2) 中 fac(1);没有使用 直接丢弃
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 ]{76: GETBP}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 12 ]{77: CSTI 1}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 12 1 ]{79: ADD}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 13 ]{80: LDI}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 9 ]{81: GETBP}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 9 12 ]{82: CSTI 2}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 9 12 2 ]{84: ADD}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 9 14 ]{85: LDI}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 9 1 ]{86: GETBP}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 9 1 12 ]{87: CSTI 0}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 9 1 12 0 ]{89: ADD}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 9 1 12 ]{90: LDI}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 9 1 2 ]{91: MUL}
[ 0 6 -999 3 0 21 3 3 4 0 74 7 2 9 1 9 2 ]{92: STI} fac(2) *res = tmp * n
^^*res
[ 0 6 -999 3 0 21 3 3 4 2 74 7 2 9 1 2 ]{93: INCSP -1}
[ 0 6 -999 3 0 21 3 3 4 2 74 7 2 9 1 ]{95: INCSP -1}
[ 0 6 -999 3 0 21 3 3 4 2 74 7 2 9 ]{97: INCSP 0}
[ 0 6 -999 3 0 21 3 3 4 2 74 7 2 9 ]{99: RET 1} fac(2) 返回到 fac(3)
[ 0 6 -999 3 0 21 3 3 4 2 9 ]{74: INCSP -1}
[ 0 6 -999 3 0 21 3 3 4 2 ]{76: GETBP}
[ 0 6 -999 3 0 21 3 3 4 2 7 ]{77: CSTI 1}
[ 0 6 -999 3 0 21 3 3 4 2 7 1 ]{79: ADD}
[ 0 6 -999 3 0 21 3 3 4 2 8 ]{80: LDI}
[ 0 6 -999 3 0 21 3 3 4 2 4 ]{81: GETBP}
[ 0 6 -999 3 0 21 3 3 4 2 4 7 ]{82: CSTI 2}
[ 0 6 -999 3 0 21 3 3 4 2 4 7 2 ]{84: ADD}
[ 0 6 -999 3 0 21 3 3 4 2 4 9 ]{85: LDI}
[ 0 6 -999 3 0 21 3 3 4 2 4 2 ]{86: GETBP}
[ 0 6 -999 3 0 21 3 3 4 2 4 2 7 ]{87: CSTI 0}
[ 0 6 -999 3 0 21 3 3 4 2 4 2 7 0 ]{89: ADD}
[ 0 6 -999 3 0 21 3 3 4 2 4 2 7 ]{90: LDI}
[ 0 6 -999 3 0 21 3 3 4 2 4 2 3 ]{91: MUL}
[ 0 6 -999 3 0 21 3 3 4 2 4 6 ]{92: STI} fac(3) *res = tmp * n
^^^*res
[ 0 6 -999 3 6 21 3 3 4 2 6 ]{93: INCSP -1}
[ 0 6 -999 3 6 21 3 3 4 2 ]{95: INCSP -1}
[ 0 6 -999 3 6 21 3 3 4 ]{97: INCSP 0}
[ 0 6 -999 3 6 21 3 3 4 ]{99: RET 1} fac(3) 返回到main(3)
[ 0 6 -999 3 6 4 ]{21: INCSP -1}
[ 0 6 -999 3 6 ]{23: GETBP}
[ 0 6 -999 3 6 3 ]{24: CSTI 1}
[ 0 6 -999 3 6 3 1 ]{26: ADD}
[ 0 6 -999 3 6 4 ]{27: LDI} (bp + 1) ==> r
[ 0 6 -999 3 6 6 ]{28: PRINTI} //print r; 输出6
6 [ 0 6 -999 3 6 6 ]{29: INCSP -1} // print语句,丢弃返回值;
[ 0 6 -999 3 6 ]{31: INCSP -1} main 是void 函数 ; 调整栈,放弃返回值
[ 0 6 -999 3 ]{33: RET 0} main(0) ret 1 -1
[ 0 3 ]{6: STOP} //3 是无用值 junk value
//0 是int t
## 指令生成说明
CALL m, a
m是参数个数, a 是跳转地址
RET m
若函数声明为 int fac(n) RET m 与 CALL m 对应,由于 microC 中 fac 为void 故 RET m-1 比 CALL m值小1
INCSP n
如赋值语句 a = n; 函数调用 fac(3); 后面都生成 INCSP -1,放弃栈上的值
语句块内的变量声明 { int tmp; .... } 在块入口 生成 INCSP 1 ,块出口生成 INCSP -1
IFZERO/IFNZER
EQ 语句后面 IFZERO a 表示 if false , 对应 if else分支 ,假值跳转
While(e) 语句入口 先GOTO跳转到 判断IFNZER处, 真值跳回入口
GETBP
GETBP 得到当前栈帧基地址 bp
bp+0 对应函数第1个参数/局部变量
bp+1 ........ 2..............
LDI将 栈帧上 某位置的值入栈 s,s(i) --> s,v ;
STI将 值写入栈上某个位置 s,i,v ---> s,v ; s(i) <= v