【问题标题】:Implement C=|A-B| with inc,dec,jnz (A,B are non-negative)实施 C=|A-B| with inc,dec,jnz (A,B 为非负数)
【发布时间】:2016-07-06 04:29:40
【问题描述】:

这是我在一次采访中看到的一个问题:

A,B 是非负数,你需要返回 C=|A-B|您只有以下说明:

  • INC 寄存器 - 寄存器加一
  • DEC 寄存器 - 从寄存器中减一
  • JNZ LABEL - 如果最后一条指令结果不为零,则跳转到标签

另外你可以使用其他初始值为零的寄存器。

我将如何解决这个问题?

【问题讨论】:

  • 只需在循环中递减两者,直到其中一个为零。另一个显然是结果。
  • @Jester:如果你在循环中递减两者,你如何在 jnz 之前测试两者?
  • 我把它作为练习留给了读者。显然,在每次循环迭代中,您都需要减少两者,如果第一个变为零,您需要退出循环并在外部减少另一个以进行补偿。你认为这需要一个答案吗?
  • @Jester:我认为这比评论要复杂得多。我怀疑您需要通过使用非零临时寄存器来构造无条件跳转,您也可以使用 inc/dec,所以 jnz 总是跳转。它变得有点复杂......
  • 我投票结束这个问题,因为它是代码高尔夫。

标签: assembly


【解决方案1】:

只需在循环中递减两者,直到其中一个为零。另一个显然是结果。

    inc a
    inc b      ; make sure input is not zero
loop:
    dec a
    jnz skip
    dec b
    mov eax, b ; return b as answer
    ret
skip:
    dec b
    jnz loop
    mov eax, a ; return a as answer
    ret

【讨论】:

  • 嗯,有趣。而且,想想看,你显然不能避免一些其他的指令(ret),这样就可以了......
  • 这是否处理 A 或 B 中的一个或两个为零的情况?
  • 好点,我不知何故将“非负面”误解为正面,呵呵。
  • 实际上我认为它仍然有效,如果非常缓慢的话。它会旋转 2^32 次,直到它回到零。显然不是你想要的真实代码,但应该适用于这个虚构的任务。
  • 即使 A = 0, B = 1?
【解决方案2】:

仅允许说明的解决方案可能是这样(虽然不优雅)。 伪寄存器 ab 保存操作数,伪寄存器 c 保存结果(如所述,最初为零)。

_dec_a:
 dec a
 inc a
jnz _dec_b

;a is zero here

  _a_zero_dec_b:
   dec b
   inc b
  jnz _a_zero_b_non_zero

;a and b are zero here 

   ;;C is the result
   inc c
   jnz _result

 _a_zero_b_non_zero:
   dec b
   inc c
 jnz _a_zero_dec_b

   ;CANNOT FALL HERE

_dec_b:
 dec b
 inc b
jnz _subtract

;b is zero here

 _b_zero_dec_a:
  dec a
  inc a
 jnz _b_zero_a_non_zero

;a and b are zero here

  ;; C is the result
  inc c
  jnz _result

 _b_zero_a_non_zero:
  dec a
  inc c
 jnz _b_zero_dec_a

  ;CANNOT FALL HERE


_subtract:
 dec a
 dec b
jnz _dec_a

 ;Result
_result:
 dec c

【讨论】:

    【解决方案3】:

    我看到的原始问题是:

    使用 jnz、inc、dec 和 halt 实现 abs(a - b)

    我的回答:

    不需要使用 mov eax 命令。只需使用可用命令将结果存储在结果寄存器中。 该解决方案将 A 和 B 都递减,直到其中一个为零,然后将另一个的值设置为 RES 寄存器并停止程序执行。 (当程序停止时,结果将在 RES 寄存器中)。

    我的代码如下所示:

    // define/map names to the registers
    #define A   R0
    #define B   R1
    #define RES R2
    
    // This solution uses the assumption that A and B are not holding init value of negative numbers values.
    
    // clear result if not already cleared.
    DEC RES; // in case it was already cleared, this step will prevent counting through all possible values.
    CLEAR_RESULT:
        INC RES;
        JNZ CLEAR_RES;
    
    INC A; // to handle a case of A is initially zero
    INC B; // to handle a case of B is initially zero
    
    DEC_A:
        DEC A;
        JNZ DEC_B;
        //Now A is zero, and the result is B-1;
    SET_B_TO_RES:
        INC RES;
        DEC B;
        JNZ SET_B_TO_RES;
        DEC RES; // compensate the incr that was initially done to handle value of 0 (should only be done here...)
        HALT;
    
    DEC_B:
        DEC B;
        JNZ DEC_A;
        //Now B is zero, and the result is A;
    SET_A_TO_RES:
        INC RES;
        DEC A;
        JNZ SET_A_TO_RES;
        HALT;
    
    // test values:
    // =============
    // A B
    // 0 2 // A is zero
    // 2 0 // B is zero
    // 1 4 // A is smaller than B
    // 5 2 // B is smaller than A
    // 2 2 // A is equal to B
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-29
      • 2015-06-12
      • 1970-01-01
      • 1970-01-01
      • 2011-05-30
      相关资源
      最近更新 更多