昨天我参加的考试中提到的一个问题让我很着迷。
G:
CMP R0,#100 [Register R0 has the argument. Also the return value.]
BLT Label [Branch if less than]
SUB R0,#10
RET
Label:
ST R14, [SP] [Store the return address of the caller on stack]
SUB SP,#4 [Update the stack pointer]
ADD R0,#11
BL G [G(n+11)] Uses value in R0 as argument, Returns value in R0
BL G [G(G(n+11))] same comments as above
ADD SP,#4
LD R14,[SP]
RET
我们被要求从四个选择中选择G(10)的正确结果。我回到家里,在我的电脑上写下程序,然后把91作为答案。事实上,91被列为答案之一。
决心达到相同的答案,我手动编写了一个相当于得到答案的汇编程序[思考在它们全部展开之前最多会产生10-12个堆栈帧]。
Type[] coltypes = {string, string, string, string, string, string };
然后我为每次调用手动重新创建堆栈帧,并且帧不断增加。在大约20个堆叠帧,我放弃了。
我的装配程序可疑,我继续在C程序中插入一个计数器,它表示该功能已输入183次。
显然,这是一个需要在5分钟内解决的问题,因此必须有一个更简单的解决方案,如拇指规则或图表等。
你怎么能在不到5分钟内得到答案?
答案 0 :(得分:4)
如果n>那么G(n)是什么? 100?
如果n = 100,G(n)是多少?
如果n = 99,G(n)是多少? (使用上面的答案)。
如果n = 98,G(n)是多少? (使用上面的答案)。
...
如果n = 90,G(n)是多少? (使用上面的答案)。
如果n = 89,那么G(n)是多少? (使用n = 100和n = 91的答案)。
等等。会有一个非常非常明显的模式。
答案 1 :(得分:0)
Note that an optimizing compiler will rearrange the code a bit and generate a tail recursive loop:
G proc
mov eax, DWORD PTR [esp+4] ;n
add eax, 11
cmp eax, 100
jle SHORT G0
add eax, -10
jmp SHORT G1
G0: push eax
call G
add esp, 4
G1: cmp eax, 100
jle SHORT G2
add eax, -10
ret 0
G2: mov DWORD PTR [esp+4], eax ;n
jmp G ;tail recursion
G endp