在我的一次采访中,我在一个'新的'原始集合中遇到了一个非常复杂的问题(当他们告诉我他们基于Python的QA测试时,为什么地狱QA需要汇编知识?),这是是这样的:
假设您的汇编语言仅包含以下说明:
'inc REG'
:将给定的寄存器增加一个。'dec REG'
:将给定的寄存器减1。'jnz LABEL'
:如果前一条指令的结果不为零,则跳转到给定的LABEL。'HELT'
:停止运行。任务:A和B寄存器保持非负值。 程序应该计算A * B的值并将结果定位在C. 此外,该语言包含寄存器C,D,...,Z,您可以假设它们在程序开始时被初始化为零。
这里有几点需要更多的关注,比如你必须事先考虑A和\或B值可能为零..并且多个零是......零...这是该死的...
P.S。由于这个问题,我没有达到'my_atoi()'问题的实现......: - (
谢谢!
答案 0 :(得分:5)
我不打算给出完整的答案,但关键是你必须自己定义一个mov
程序。假设dec X
X
保持为0会产生负数(或非常大),可以这样做:
MOV_AD: ; copy value in A to D, using E as scratch space
inc A ; must be non-zero for jnz to work below
COPYLOOP:
inc D
inc E
dec A
jnz COPYLOOP
dec D ; undo the first inc A in D
; E now contains the initial value of A + 1
MOVBACK: ; move value in E back to A
inc A
dec E
jnz MOVBACK
dec A ; undo the first inc A
WIPE_E: ; wipe the scratch space
dec E
jnz WIPE_E
一旦有了适当的mov
例程,就可以将重复增量和乘法实现为重复加法。在两者中,您需要使用inc
技巧才能使jnz
起作用,并且在乘法例程中,您需要以减法结束。
答案 1 :(得分:3)
逐步打破这一步:
原件:
C = A * B
相当于:
C = 0
while A != 0:
dec A
C += B
相当于:
C = 0
while A != 0:
dec A
# Note: Following block of code changes B but sets it back to
# original value when done
Z = 0
while B != 0:
dec B
inc Z
inc C
B = Z
相当于:
C = 0
Z = 0
while A != 0:
dec A
# Note: Following block of code changes B but sets it back to
# original value when done
while B != 0:
dec B
inc Z
inc C
while Z != 0:
dec Z
inc B
现在我们只需要弄清楚如何翻译这个结构:
while LOOP_VAR != 0:
dec LOOP_VAR
... some code here which does not use LOOP_VAR ...
可以翻译为:
# Next 4 lines do "if LOOP_VAR == 0: goto loop_end"
inc LOOP_VAR
dec LOOP_VAR # To set flags
jnz loop_again
goto loop_end
loop_again:
... some code here which does not use LOOP_VAR ...
dec LOOP_VAR
jnz loop_again
loop_end:
当然,我们需要将无条件转换为条件转换。幸运的是,我们有许多已知为零的变量,因此我们可以测试其中一个变量是否为零:
# Unconditional jump to "loop_end". Note that Q is always zero.
inc Q
dec Q
jnz loop_end
所以,把所有这些放在一起:
# Next 3 lines do "if A != 0: goto outer_loop_again"
inc A
dec A # To set flags
jnz outer_loop_again
# Unconditional jump to "outer_loop_end". Note that Q is always zero.
inc Q
dec Q
jnz outer_loop_end
outer_loop_again:
# Next 3 lines do "if B != 0: goto addition_loop_again"
inc B
dec B # To set flags
jnz addition_loop_again
# Unconditional jump to "addition_loop_end". Note that Q is always zero.
inc Q
dec Q
jnz addition_loop_end
addition_loop_again:
inc Z
inc C
dec B
jnz addition_loop_again
addition_loop_end:
# Next 3 lines do "if Z != 0: goto move_loop_again"
inc Z
dec Z # To set flags
jnz move_loop_again
# Unconditional jump to "move_loop_end". Note that Q is always zero.
inc Q
dec Q
jnz move_loop_end
move_loop_again:
inc B
dec Z
jnz move_loop_again
move_loop_end:
dec A
jnz outer_loop_again
outer_loop_end:
# Finished!
helt
编辑补充:实际上,有一种稍微简单的方法。我们可以在开始时检查A或B是否为零,这简化为:
# Check if A is zero, and halt if so
# (So that multiplying by zero gives zero)
inc A
dec A # To set flags
jnz a_non_zero
helt # Multiplying by zero gives zero
a_non_zero:
# Check if B is zero, and halt if so
# (So that multiplying by zero gives zero)
inc B
dec B # To set flags
jnz b_non_zero
helt # Multiplying by zero gives zero
b_non_zero:
outer_loop_again:
addition_loop_again:
inc Z
inc C
dec B
jnz addition_loop_again
move_loop_again:
inc B
dec Z
jnz move_loop_again
dec A
jnz outer_loop_again
# Finished!
helt
答案 2 :(得分:2)
JNZ 指令可以看作 做..而 结构,{{3代码:
@_loop1: ; do {
; do {
INC Z ; z++;
INC C ; c++;
DEC B ; b--;
JNZ _loop1 ; } while (b != 0);
;
@_loop2: ; do {
INC B ; b++;
DEC Z ; z--;
JNZ _loop2 ; while (z != 0);
;
DEC A ; a--;
JNZ _loop1 ; } while (a != 0);
答案 3 :(得分:0)
我刚刚在JJ面试中完成了这项任务。这似乎是正确的解决方案。如果我错了请纠正我
INC A
DEC A
JNZ L0
HELT
L0:
INC B
DEC B
JNZ L1
HELT
L1:
INC C
INC D
DEC A
JNZ L1
DEC B
JNZ L2
HELT
L2:
INC C
INC A
DEC D
JNZ L2
DEC B
JNZ L1
HELT