-
-
[讨论]关于《加密与解密》(第二版)的一些问题
-
发表于:
2007-5-19 11:41
5235
-
前几天买了一本《加密与解密》(第二版),是第一次印刷的。同时也在看雪的主页上下载了勘误表。不过在阅读的过程中还是发现了一些问题,在此写出,请大家讨论。也许很多问题已经在第二次印刷时被纠正,不过我看勘误表上也有关于第一次印刷的。也许很多所谓的问题也许是我个人理解上的偏差,更说不定我的书是盗版的所以会有这些问题,所以还请各位高手们多多包涵。
暂时只读完了第二章,所以就先谈谈第二章的问题。
26页9行:call dword ptr [eax*edx+2]
注:我一年多前学的x86汇编,似乎怎么也记不起来有eax*edx+2这样的寻址方式,而应该是[基址+变址*2^n+偏移]的格式。否则,就不需要乘法指令了,直接lea eax,[eax*edx]不就是算了乘法么。
28页2.2.2下面的第一行:其中r/m8表示8位寄存器。
注:这话说得不全,r/m8应该表示8位寄存器或单字节内存单元。
30页表的第二项:
测试寄存器的值是否为0xffffffff
第二种代码:
inc eax
je label
dec eax
作者的意思很清楚明了,可是愚以为,当然,如果eax的值不是0xffffffff到还好,如果eax的值真的是0xffffffff,跳转发生,可是这是jmp,而不是call,没有任何保证说程序流程一定会回到dec eax,这样说来,仅仅一个测试,就把eax的值破坏了,而且没有任何迹象显示恢复eax的那条dec eax一定会被执行。如果label标签下的代码需要eax来进行操作或者什么的,整个过程都会出问题。而前一种用cmp指令就很干净,不会有任何副作用。
37页的表:
注:表的上一行已经说了是用高级语言C来描述,可是表里的方案三怎么看着就是不地道呢?C的语法里面似乎没有这样的形式吧,我想作者的意思是不是想说do-while循环:
i=0
do
{
i++;
……
}
while(i<=5)
还有方案一:
while(i<5)
{
……
}
这个程序的行为不确定,首先就是没有对i进行初始化,再者就算初始化了,也是一个死循环,原因很简单,在while循环里没有对i进行更新。
建议更改如下:
i=0;
while(i<5)
{
i++;
……
}
38页2.3.4节向下第6行:mov eax,dword prt [00543380]
ptr被误写为prt了。需要注意的是立即数寻址中的00543380,很明显这条指令是反汇编出来的,也就是说是调试器反汇编的代码。在很多地方也出现了类似的情况。应该和汇编编程所书写的代码区别的是(比如用MASM),除非在编译器里设置默认进制,否则默认数字就是十进制,那么在编程时,输入十六进制数据应该在末尾标注,比如[543380h]。有趣的是,在文中有些地方标注了,有些地方又没标注,显得比较乱。
39页2.3.5节第二行起:
mov [esp+3Ch+var_A],4
mov [esp+3Ch+var_9],6
mov [esp+3Ch+var_7],dl
mov [esp+3Ch+var_6],10h
mov [esp+3Ch+var_3],4
mov [esp+3Ch+var_2],10h
这段代码有的数字后面加了十六进制标号,有的没加(那就是十进制),按照上面讲的,应该是汇编语言的编程源代码,而非反汇编输出。在书中之前的很多地方,都看到了类似mov eax,dword ptr [xxxxxxxx]这样的代码,而在这里又看到了类似mov [esp+3Ch+var_9],6这样的代码。在我学汇编的时候,有一个印象,就是从编译器的角度考虑语法。比如mov eax,dword ptr [xxxxxxxx]完全可以写成mov eax,[xxxxxxxx] ,原因是,编译器通过两个操作对象可以很容易判断传数操作应该是32位,因为其中有一个操作对象是32位寄存器,总不会只往寄存器里的一半传吧。而形如mov [esp+3Ch+var_9],6这样的代码就不行,因为编译器不知道应该是把8位的0x06送到8位的内存单元里,还是把16位的0x0006送到16位的内存单元里,抑或是把32位的0x00000006送到32位的内存单元里。所以在将立即数传入内存时必须注明是多少位的。当然,mov eax,dword ptr [xxxxxxxx]这样的命令虽然多此一举(作为汇编源程序),不过并不算错误。
[注意]看雪招聘,专注安全领域的专业人才平台!