简体   繁体   English

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

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

So we have like this safes challenge in assembly, you need to create safes and keys that will break them and end the infinite loop.所以我们在组装中遇到了这样的保险箱挑战,你需要创建保险箱和钥匙来打破它们并结束无限循环。 Here's an example for a safe:下面是一个保险箱的例子:

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

and a key:和一把钥匙:

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

So I have a safe and a key, and I don't understand why it doesn't work:所以我有一个保险箱和一把钥匙,我不明白为什么它不起作用:

here's my safe:这是我的保险箱:

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

And here's my key:这是我的钥匙:


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


ret

The right answer to break the loop should be 10 and it works when I put in on the safe, somehow with the key it doesn't work and I can't figure out why.. (the "word" is needed for nasm)打破循环的正确答案应该是 10,当我放入保险箱时它会起作用,但不知何故它不起作用,我不知道为什么..(nasm 需要“词”)

The value in dx used as the counter for the loop instruction comes from the first mul instruction. dx用作loop指令计数器的值来自第一条mul指令。

This multiplication is just doubling the key, so dx is either 0 or 1 (an easy way to see this is to think of the multiplication as a left shift by one or by remembering that the sum of two n-bit numbers has at most n+1 bits)这个乘法只是将密钥加倍,所以dx是 0 或 1(一个简单的方法是将乘法视为左移 1 或记住两个 n 位数字之和至多有n +1位)


If dx is zero, the whole loopy1 block does nothing (as dx also sets ax ) and the value in ax at the end of the safe is 7*(5 +2k) where k is the key (see the commented code below).如果dx为零,则整个loopy1块什么都不做(因为dx也设置了ax )并且保险箱末尾的ax中的值是 7*(5 +2k) 其中k是键(请参阅下面的注释代码)。

It is then easy to see that 350 = 7*(5+2k) => 2k = 45 has no solution.然后很容易看出 350 = 7*(5+2k) => 2k = 45 没有解。 Therefore no key for which dx is zero can unlock the safe.因此,没有dx为零的钥匙可以解锁保险箱。
A key has dx 0 iif its value is less than 32768 (again, this is easy to see when thinking of the multiplication as a left shift by one).如果键的值小于 32768,则键的dx 0(同样,将乘法视为左移 1 时很容易看出这一点)。

Corollary: 10 cannot be a solution.推论: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 

If there is a key that unlocks the safe then it must be greater or equal to 32768 so that dx is 1 after the first multiplication.如果有解锁保险箱的钥匙,那么它必须大于或等于 32768,以便在第一次乘法后dx为 1。 With this condition, the value in ax at the end of the safe can be written as 7*(6 + (2k & 0xffff)) => k & 0x7fff = 22.在这种情况下,保险箱末端ax中的值可以写为 7*(6 + (2k & 0xffff)) => k & 0x7fff = 22。
Adding the condition stated at the very beginning of this section, the final value for k is 32768 + 22 = 32790 or 0x8016 in hex .加上本节开头所述的条件k的最终值为 32768 + 22 = 32790 或 0x8016(十六进制) I've leaped quite a few logical steps in manipulating the equation and forming the result but, again, thinking of 2k as a shift may help visualize them.我在操纵方程和形成结果方面已经跳过了很多合乎逻辑的步骤,但是,再次将2k视为一种转变可能有助于将它们可视化。

Corollary: Due to the algebraic structure involved, this is the only solution.推论:由于涉及代数结构,这是唯一的解决方案。

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 

Considering that you have a mov dx, 5 before the first multiplication, did you (or the author of the safe) forget that mul affects dx ?考虑到您在第一次乘法之前有一个mov dx, 5您(或保险箱的作者)是否忘记了mul影响dx
If you wrap the first mul in push dx / pop dx (or just move mov dx, 5 after it), you would get, at the end of the safe, a value in ax equals to 7*(30 +2k) which implies k = 10 indeed.如果你将第一个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