[英]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.