繁体   English   中英

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

[英]Assembly safes and keys- why it won't work?

所以我们在组装中遇到了这样的保险箱挑战,你需要创建保险箱和钥匙来打破它们并结束无限循环。 下面是一个保险箱的例子:

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 需要“词”)

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(同样,将乘法视为左移 1 时很容易看出这一点)。

推论: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
如果你将第一个mul包裹在push dx / pop dx (或者只是移动mov dx, 5在它之后),你会得到,在保险箱的最后, ax的值等于 7*(30 +2k) 这意味着k = 10确实。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM