Assembly 与inc、dec、jnz一起实施C=| A-B |(A、B为非负)
这是我在采访中看到的一个问题: A、 B是非负数,您需要返回C=| 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
- 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