Introduction to Computer Science
Homework 07
1.
3.4.1
b, c = 2, 4
def g_func(d):
global a # a为全局变量
a = d * c # d为局部变量;a、c为全局变量,这里改变了全局变量a的值
g_func(b)
print(a)
# 程序运行结果
8
3.4.2
a = 10
def func():
x = a
print(x)
func()
print(a)
# 程序运行结果
10
10
3.4.3
a = 10
def func(b):
c = a + b
print(c)
func(1)
a
为全局变量;b
为局部变量
# 程序运行结果
11
3.4.4
分析:
-
全局变量
a
赋值3 -
全局变量
b
赋值2 -
全局变量
c
赋值1 -
a
、b
作为参数传给do_add()
-
【在
do_add()
中】-
将局部变量
c
的值修改为a+b #5
,全局变量c=1
不变 -
将
c
、1
作为参数传给do_sub()
-
【在
do_sub()
中】-
将局部变量
c
的值修改为a-b #4
-
将
c
、c
作为参数传给do_mul()
- 【在
do_mul()
中】- 将全局变量
c
的值修改为a*b #c*c=16
- 打印c:输出16
- 返回c
- 将全局变量
- 【在
-
do_mul()
返回16,将16赋值到局部变量c
-
将
c
、2
作为参数传给do_div()
- 【在
do_div()
中】- 将局部变量
c
的值修改为a/b #8.0
- 打印c:输出8.0
- 返回c
- 将局部变量
- 【在
-
do_mul()
返回8.0,将8.0赋值到局部变量c
-
打印c:输出8.0
-
返回c
-
-
-
do_sub()
返回8.0,将8.0赋值到全局变量c
-
打印c:输出8.0
-
-
此时全局变量
c
的值为16。打印c:输出16
# 程序运行结果
16
8.0
8.0
8.0
16
3.4.5
a = 10
def func(a):
global a
a = 20
print(a)
func(a)
print(a)
a
同时用作形式参数与全局变量
3.4.6
a = 10
def func():
a = a + 10
print(a)
func()
print(a)
a
在函数中位于等号左侧,则会先创建一个局部变量;位于等号右侧时,先查找a
是否局部变量,若找不到则使用全局变量。等号左右的变量a
出现矛盾,因而报错。
2.
3.14
a = 10
b = 30
def func():
global a
a = a + b
return a
b = func()
print(a,b)
# 程序运行结果
40 40
3.15
a = 10
b = 30
def func(a,b):
a = a + b
return a
b = func(a,b)
print(a,b)
# 程序运行结果
10 40
3.16
def func(b):
a = b + 10
print(b)
b = 15
print(a,b)
func(20)
# 程序运行结果
20
30 15
3.19
def do_sub(y):
z = 4
z = y - z
return z
x = do_sub(13)
3.21
# Program 1
y = 5
def func(z):
global x
x = z - y
print(x)
func(11)
# 输出结果
6
# Program 2
def func(z):
y = 5
x = z - y
print(x)
func(11)
# 输出结果
6
两个程序的栈帧中存储的数据不相同。Program 1 中
x
、y
为全局变量,执行完函数后该数据不会弹出;Program 2 中x
、y
为局部变量,执行完函数后该数据会弹出。
3. SEAL. 累加列表非1数
data = [2, 1, 4, 1, 5, 6, 1, 7, 2, 1, 3, 4]
s = 0
for i in range(12):
if data[i] != 1:
s += data[i]
print(s)
_data 1,[2, 1, 4, 1, 5, 6, 1, 7, 2, 1, 3, 4]
mov R1,0 # 存结果
mov R2,0 # 计数
mov R5,1 # 索引
L1:
slt R3,R2,12
beqz R3,L2 # 若计数小于12,继续执行,否则跳转L2
load R4,0(R5) #将索引对应的值载入R4
add R5,R5,1 # 索引+1
add R2,R2,1 # 计数+1
xor R6,R4,1 # 若R4=1,R6=0
beqz R6,L1 # 若R6!=0,继续执行,否则跳转L1
add R1,R1,R4 # 若R6!=0,R4累加入R1
goto L1 # 跳转L1
L2:
_pr R1 # 打印R1
# 程序运行结果
33
4. SEAL. 统计正整数二进制1个数
x = 13
cnt = 0
while(x != 0):
if x & 1 == 1:
cnt += 1
x >>= 1
print(cnt)
mov R0,13 # 存输入
mov R1,0 # 计数器
L1:
beqz R0,L2 # 若R0!=0,继续执行,否则跳转L2
and R2,R0,1 # R0与1位与,结果存在R2
shiftr R0,R0,1 # R0右移1位
beqz R2,L1 # 若R2=1,继续执行,否则跳转L1
add R1,R1,1 # 计数器加一
goto L1
L2:
_pr R1 # 打印R1
# 程序运行结果
3
5. SEAL. 列表中奇数个数
data = [5,2,8,11,31,25,101]
cnt = 0
for i in range(len(data)):
if data[i] & 1 != 0: # n&1 != 0 代替 n%2 != 0;二者等价
cnt += 1
print(cnt)
_data 1,[7,5,2,8,11,31,25,101]
mov R1,0 # 存结果
mov R2,0 # 计数
mov R3,1 # 索引
load R4,0(R3) # 存列表长度
add R3,R3,1 # 索引指向列表第2个元素(列表的正式开始)
L1:
slt R5,R2,R4
beqz R5,L2 # 若计数小于R4,继续执行,否则跳转L2
load R6,0(R3) # 将索引对应的值载入R6
add R3,R3,1 # 索引+1
add R2,R2,1 # 计数+1
and R6,R6,1 # R6与1求位与,结果存入R6
beqz R6,L1 # 若R6!=0,继续执行,否则跳转L1
add R1,R1,1 # 若R6!=0,R1+1
goto L1 # 跳转L1
L2:
_pr R1
# 程序运行结果
5
6. SEAL. 求三个数最大值
def get_max(x,y):
if x <= y:
return y
else:
return x
a = 7
b = 18
c = 9
print(get_max(get_max(a,b),c))
mov R15,300 # 代表fp,基地址300
mov sp,R15 # sp=fp
sub sp,sp,3 # sp向上3个单位,开辟空间存a,b,c
mov R2,7 # R2 ← a=7
mov R3,18 # R3 ← b=18
mov R4,9 # R4 ← c=9
store -1(R15),R4 # c、b、a倒序存参
store -2(R15),R3
store -3(R15),R2
push R3 # 传参b
push R2 # 传参a
call Lmax # 调用max(a,b),返回值存R1
push R4 # 传参c
push R1 # 传参max(a,b)的返回值
call Lmax
goto Lprint
Lmax: # R1 ← max(a,b)
push R15 # 存旧的fp
mov R15,sp # 复位fp,令fp=sp(fp拉上去)
push R2 # 把函数会被更改的R2,R3,R4存入栈(存档)
push R3
push R4
load R2,2(R15) # 存函数第一个参数
load R3,3(R15) # 存函数第二个参数
sle R4,R2,R3 # 若R2<=R3,R1←R3,否则跳转L100
beqz R4,L100
mov R1,R3
goto Lreturn
L100:
mov R1,R2 # R1←R2
Lreturn:
pop R4 # 恢复原来存入栈的R4、R3、R2的值
pop R3
pop R2
mov sp,R15 # 令fp=sp(sp拉下来)
pop R15 # 归位fp(fp下去调用函数之前fp的位置)
ret
Lprint:
_pr R1
# 程序运行结果
18
-
max(a,b)
调用时依次push R15 R2 R3 R4 到栈帧- R15: 存旧的 fp
- R2~4: 存函数调用之前寄存器中存储的值
-
最前三个指令:
- 定位 fp,即确定基地址
- 令 fp=sp
- 令 sp-n,即开拓局部变量存储的 n 个空间,sp 指向栈顶
-
最后三个指令:
- 令 fp=sp,释放建立的栈帧
- 弹出旧的fp,令fp回复函数调用之前的位置
- ret,即pop pc,(与call L 相对应。call L 相当于 push pc 并跳转并执行函数L)返回到 call 的下一条指令。
7. SEAL. 求x的所有因数
def factors(x): # 找到x的因数
y=x//2
for i in range(2,y+1):
if (x %i ==0): # 发现i是x的因数
print("Factor:",i);
factors(x//i) # 递归调用自己,参数变小是x//i
break # 跳出for循环
else: # 假如离开循环正常,没有碰到break,就执行else内的print,x是质数
print("Prime Factor:",x)
print("参数x:%d, 变量y:%d" %(x,y))
return
factors(18)
mov R15,10000 # 代表fp
mov sp,R15 # 使sp=fp
mov R1,18 # 对应x
push R1 # 传参x
call Lfac
goto L0
Lfac:
push R15
mov R15,sp
load R1,2(R15)
div R2,R1,2 # y
push R2
mov R3,2 # i
Lloop:
sle R4,R3,R2 # 循环终止条件
beqz R4,Lprime
div R5,R1,R3 # 判断因数
mul R6,R5,R3
sub R6,R6,R1
beqz R6,Longo
add R3,R3,1
goto Lloop
Longo:
_pr 'Factor:',R3
push R3
push R5
call Lfac
goto Ldisplay
Lprime:
_pr 'Prime Factor:',R1
Ldisplay:
load R1,2(R15)
load R2,-1(R15)
_pr '参数x:',R1,'变量y:',R2
mov sp,R15
pop R15
ret
L0: # 程序结束
# 程序运行结果
Factor: 2
Factor: 3
PrimeFactor: 3
参数x: 3 变量y: 1
参数x: 9 变量y: 4
参数x: 18 变量y: 9
#SEAL指令速查手册
load R1,(address) # R1←(address) 即主存adress中的变量
load R1,offset(R2) # R1←(R2+offset)
store (address),R1 # (address)←R1
store offset(R2),R1 # (R2+offset)←R1
mov R1,R2 # R2←R1
add R1,R2,R3 # R1←R2+R3
sub R1,R2,R3 # R1←R2-R3
slt R1,R2,R3 # if R2<R3, R1←1 else R1←0
sle R1,R2,R3 # if R2<=R3, R1←1 else R1←0
beqz R1,L1 # if R1 = 0 goto L1
bneqz R1,L1 # if R1 != 0 goto L1
call L1 # 调用L1标签下的函数
ret # 返回并继续call下一条语句
_data first_address,[a0,a1,...,an]
_pr
标签:R1,R2,R3,Introduction,Science,mov,Computer,func,print
From: https://www.cnblogs.com/LeeHero/p/16979352.html