组装保险箱和钥匙-为什么不起作用?

时间:2019-12-28 16:06:49

标签: debugging assembly emu8086

因此,我们在组装时遇到了这种保险柜挑战,您需要创建保险柜和钥匙以破坏它们并结束无限循环。 这是一个安全的示例:

loopy:
mov ax, [1900]
cmp ax,1234
jne loopy

和一个键:

loopy2:
mov ax, 1234
mov [1900],ax
jmp loopy2

所以我有一个保险柜和一把钥匙,而且我不明白为什么它不起作用:

这是我的保险箱:

org 100h
mySafe:  
mov dx,5
mov ax, [5768h] 
mov bx,7 
mov word [180h],2
mul word [180h]
mov [180h],bx
push ax
dec bx
mov cx,dx
mov ax,dx
loopy1:
add bx,ax
loop loopy1
dec bx
pop ax
add ax,bx
mul word [180h]
cmp ax,350
jne mySafe

这是我的钥匙:


org 100h
loopy:
mov word [5768h],10
jmp loopy


ret

打破循环的正确答案应该是10,当我把它放在保险柜上时,它会起作用,用某种方式,钥匙不起作用,我也不知道为什么。 (nasm需要“ word”)

1 个答案:

答案 0 :(得分:2)

dx中用作loop指令计数器的值来自第一条mul指令。

此乘法只是将键加倍,因此dx可以是0或1(一种简单的方法是将乘法视为左移1或记住两个n的和位数字最多具有 n + 1 位)


如果dx为零,则整个loopy1块不执行任何操作(因为dx也设置了ax),并且ax中的值在末尾保险柜是7 *(5 + 2k),其中 k 是钥匙(请参见下面的注释代码)。

然后很容易看出350 = 7 *(5 + 2k)=> 2k = 45没有解。因此,dx为零的任何密钥都无法解锁保险箱。
如果键的值小于32768,则键的dx为0(同样,当将乘法视为左移一位时,很容易看到)。

推论:10不能解决。

safe:
  mov dx,5
  mov ax, [k]               ;ax = k (key)
  mov bx,7 
  mov word [aux],2    
  mul word [aux]            ;dx = 0 ax = 2k
  mov [aux],bx              ;aux = 7
  push ax                   ;ax = 2k
  dec bx                    ;bx = 6 
  dec bx                    ;bx =    5
  pop ax                    ;ax = 2k
  add ax,bx                 ;ax = 5 + 2k
  mul word [aux]            ;ax = 7*(5 +2k)

  cmp ax,350
  ret 

如果有一个可以打开保险箱的钥匙,那么它必须大于或等于32768,以便在第一次乘法之后dx为1。 在这种情况下,保险柜末端ax中的值可以写为7 *(6 +(2k&0xffff))=> k&0x7fff =22。
加上本节开头所述的条件, k的最终值为32768 + 22 = 32790或十六进制的0x8016 。 在处理方程式和形成结果时,我已经跳了相当多的逻辑步骤,但再次将2k视为转变可能会帮助他们可视化。

推论:由于所涉及的代数结构,这是唯一的解决方案。

safe:
  mov dx,5
  mov ax, [k]           ;ax = k
  mov bx,7 
  mov word [aux],2    
  mul word [aux]            ;dx:ax = 2k
  mov [aux],bx              ;[aux] = 7
  push ax                   ;dx = 1 ax = 2k & 0xffff
  dec bx                    ;bx = 6 
  mov cx,dx                 ;cx = 1
  mov ax,dx                 ;ax = 1
loopy1:
  add bx,ax                 ;bx = 6 + 1
  dec cx
jnz loopy1
  dec bx                    ;bx = 6 
  pop ax                    ;ax = 2k & 0xffff
  add ax,bx                 ;ax = 6 + (2k & 0xffff)
  mul word [aux]            ;ax = 7*(6 + (2k & 0xffff))

  cmp ax,350
  ret 

考虑到在第一次乘法之前您有mov dx, 5您(或保险柜的作者)是否忘记了mul影响dx ?< br /> 如果将第一个mul包裹在push dx / pop dx中(或仅将其后移mov dx, 5),则在保险柜的末尾,ax中的值等于7 *(30 + 2k),这实际上意味着 k = 10