我正在尝试使用adobe type 1字体加密算法加密文本文件。但是,我不知道如何在汇编语言中正确实现该算法。如果可以,请帮助我。
这是adobe type 1字体加密算法:
unsigned short int r;
unsigned short int c1 =52845;
unsigned short int c2 = 22719;
unsigned char eencrypt(char plain) unsigned char plain;
{ unsigned char cipher;
cipher = (plain ^ (r >> 8));
r = (cipher + r) * c1 + c2;
return cipher;
}
这是我的代码:
.model tiny
.data
filename db "file.txt", 0
bufferSize = 512
filehandle dw ?
buffer db bufferSize dup (0)
r dw 0
c1 dw 52845
c2 dw 22719
cipher dw ?
message1 db 'Cannot open file. $'
message2 db 'Cannot read file. $'
message3 db 'Cannot close file. $'
.code
org 100h
start:
call open
call read
call close
call Exit
;procedures
open:
mov ah,3DH
mov al,0
mov dx, offset filename
int 21h
jc openErr
mov filehandle, ax
ret
read: ;reads file
mov ah, 3Fh
mov bx, filehandle
mov cx, bufferSize
mov dx, offset buffer
int 21h
cmp ax,0
jc readErr
;displays content of file
call clear
mov ah, 9
mov dx, offset buffer
int 21h
ret
close:
mov ah, 3Eh
mov bx, filehandle
int 21h
jc closeErr
ret
encrypt:
; need loop to loop through each char, don't know how to do that
mov ax, [r]
shr ax, 8
mov bl, [buffer]
xor bh,bh
xor bx, ax
mov cipher, bx
mov dx, cipher
add dx, [r] ;get error: extra characters on line
imul dx, c1
add dx, c2
mov [r], dx
;decrypt:
clear: ;clears the screen
mov ax,003h
int 10h
ret
Exit:
mov ax, 4C00h
int 21h
newline: ;prints a newline
mov ah, 2
mov dl, 0DH
int 21h
mov dl, 0AH
int 21h
ret
;error messages
openErr :
call newline
lea DX,message1 ;set up pointer to error message
mov AH,9 ;display string function
int 21H ;DOS call
stc ;set error flag
ret
readErr :
call newline
lea DX,message2 ;set up pointer to error message
mov AH,9 ;display string function
int 21H ;DOS call
stc ;set error flag
ret
closeErr :
call newline
lea DX,message3 ;set up pointer to error message
mov AH,9 ;display string function
int 21H ;DOS call
stc ;set error flag
ret
结束开始
答案 0 :(得分:0)
;encrypt:
; need loop to loop through each char, don't know how to do that
;mov ax, r
;shr ax, 8 r>>8
;mov bl, buffer bl = buffer
buffer
是符号地址,而不是缓冲区中的值。使用mov bl,[buffer]
从内存中读取值。如果你想循环遍历整个缓冲区内容,将该地址放入某个寄存器,si
通常更有利于保持指向数据源的指针(因为它在lods
指令中是硬编码的,并且“s “可能被视为”来源“)。如果你是C ++编译器,你不关心,你选择任何备用寄存器,而不考虑它的名字。
;xor bx, ax bx = buffer ^(r>>8)
bh
未设置,可能是任何内容,破坏了您的计算。在从缓冲区加载xor bx,bx
之前执行bl
,或者仅xor bh,bh
清除bh
(在现代x86上稍微慢一点,因为它必须合并bh
+ bl
进入bx
),或者在上一步中使用movzx bx,byte ptr [buffer]
将char值零扩展为字值。
;mov cipher, bx cipher = buffer^(r>>8)
标签cipher
是在db ?
之前定义的,但是在这里你要将两个字节写入内存,因此它也会覆盖message1
字符串的第一个字节。我强烈建议每次写入内存时使用[]
,即使TASM / MASM允许这种语法,但我发现很难阅读(看到[cipher]
会让我的大脑自动思考“记忆访问“即使快速浏览一下来源。”
;mov cx, c1
c1
和c2
可以是EQU
,因此它们会直接编译为代码中的中间值。
;add cx, c2
那不是,C加密的作用(乘法优先于加法)。
;mov dx, cipher
您再次将cipher
视为单词,这是有道理的,但它与db ?
相反(因此db
需要修复,而不是此处的代码)。
;add dx, r
;imul dx, cx
我会再次在[]
周围使用r
括号,而乘法/加法顺序当然是错误的。
尝试不错,但是不要犹豫,取消注释那段代码,预先设置一些调试值的寄存器,然后直接跳转到它,在调试器中打开二进制文件,然后单步执行以验证它像你想要的那样工作。您可能很快就会找到我上面写的所有内容。
然后将其转换为循环(使用任何ASM书籍/教程以及有关使用数组/字符串的一些示例,学习使用指针,那么它应该不难完成)。