【发布时间】:2020-05-31 15:53:23
【问题描述】:
这是我在面试中遇到的一个问题,我没有找到解决方案 - 所以我尝试自己解决。
我们可以在这里使用伪代码——它不需要是正式的代码。
问题是得到无符号输入的绝对差:
假设您的汇编语言仅包含以下指令:
inc、dec、jnz和halt(halt= 停止运行)。任务:
A和B是保存非负值的寄存器。 程序应计算|A-B|的值并将结果定位到C。此外,该语言还拥有寄存器C、D、...、Z,您可以假设它们在程序启动时被初始化为零。
这是我的尝试,我的主要想法是减少两个寄存器直到一个变为零,然后将另一个寄存器的值移动到C:
// zero case handling
dec a
inc a
jnz a_pre_loop_not_zero // a != 0
// a == 0, check if b == 0
dec b
inc b
jnz move_b_to_c // a == 0, b !=0
// a == 0 , b == 0 -> c needs to be 0
halt
a_pre_loop_not_zero:
dec b
inc b
jnz main_loop // a != 0, b != 0
// a != 0 , b == 0
move_a_to_c:
inc c
dec a
jnz move_a_to_c
halt
// a,b != 0
main_loop:
dec b
jnz b_not_zero // b!=0
// b became zero before a -> a contains result+1 now
dec a
jnz move_a_to_c
halt // if a == 0 now -> a == b -> c needs to be 0
b_not_zero:
dec a
jnz main_loop // a != 0
// a became zero before b -> b contains the result now
move_b_to_c:
inc c
dec b
jnz move_b_to_c
halt
现在,我认为它可以工作 - 但它看起来很脏。
更具体地说,我认为零案例处理可以用更干净的方式完成,也许我们甚至可以在主循环中考虑它(无需在预循环代码中检查它)。
另外,我没有使用寄存器C、D、...、Z 被初始化为 0 并且可以使用的事实——这让我怀疑也许有更好的方法。
这个问题有更好的解决方案吗?
【问题讨论】:
-
你的方法看起来不错。我可能会考虑通过增加它们来跳过零处理,然后直接进入主循环。
-
@ErikEidt:如果我们也有 JZ,这将很容易;
do { if(--a == 0) break; } while(--b);但是我们可以通过一个在循环开始时为零的寄存器的虚拟 INC/JNZ 从一个 JNZ 合成一个 JZ。或非零寄存器的inc/dec/jnz。 -
我投票结束这个问题,因为它是代码高尔夫而不是实际的编程问题。
标签: algorithm assembly pseudocode