Assembly 与inc、dec、jnz一起实施C=| A-B |(A、B为非负)

Assembly 与inc、dec、jnz一起实施C=| A-B |(A、B为非负),assembly,Assembly,这是我在采访中看到的一个问题: A、 B是非负数,您需要返回C=| A-B |,其中只有以下说明: INC寄存器-向寄存器添加一个 DEC寄存器-从寄存器中减去一 JNZ标签-如果最后一条指令结果不是零,则跳到标签 此外,您可以使用初始值为零的其他寄存器 我该如何解决这个问题呢?只要在一个循环中递减这两个值,直到其中一个值为零。另一个显然是结果 inc a inc b ; make sure input is not zero loop: dec a

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

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

  • INC寄存器-向寄存器添加一个
  • DEC寄存器-从寄存器中减去一
  • JNZ标签-如果最后一条指令结果不是零,则跳到标签
此外,您可以使用初始值为零的其他寄存器


我该如何解决这个问题呢?

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

    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

只允许使用指令的解决方案可能是这样的(尽管不是优雅的)。 其中伪寄存器a和b保存操作数,伪寄存器c保存结果(如前所述,最初为零)

在我看来,最初的问题是:

使用jnz,inc,dec和halt机具abs(a-b)

我的答覆是:

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

只需在一个循环中递减两个,直到其中一个变为零。另一个显然是结果。@Jester:如果在循环中两个都递减,那么在
jnz
之前如何测试这两个呢?我把它作为练习留给读者。显然,在每个循环迭代中,您需要同时递减这两个值,如果第一个值变为零,则需要退出循环并递减外部的另一个值以进行补偿。你认为这需要一个答案吗?@Jester:我认为这比一个评论要复杂得多。我怀疑您需要使用一个非零临时寄存器来构造一个无条件的跳转,它通常是
inc/dec
,因此
jnz
总是跳转。它变得有点复杂…我投票结束这个问题,因为它是代码高尔夫。嗯,有趣。而且,仔细想想,你显然无法避免一些其他指令(
ret
),这样就可以了……这能处理A或B的一个或两个都为零的情况吗?好的一点,我不知何故将“无负”误解为正,duh。事实上,我认为它仍然有效,如果速度很慢的话。它将旋转2^32次,直到回到零。很明显,这不是您想要的真实代码,但应该适用于这个虚构的赋值。即使对于A=0,B=1?
// 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