我只学过8086汇编和C语言,看win32汇编很吃力,可是我也很努力,一边看很详细的破解文章一边上网查不懂得东西。下面是一部分:
1.xor
实例:
xor ax,ax ;清零AX,等价指令:mov ax,0h;
xor ax,0ffffh;对AX取反,等价指令:not ax;
xor ax, 0h;AX保持不变,不执行任何指令即为等价指令
xor ax,0ff00;对AH取反,对AL保持;等价指令:not ah;
xor ax,0f0f0;对AH和AL的bit4~7为取反,对AH,AL的0~3保持,没有相对简单的等价指令了
结论:xor功能很多,通常有等价指令,个别时候没有等价指令,或者等价指令相对烦琐。
2.正数的补码反码与源码相同
负数反码数值位与原码相反(符号为不变)
负数补码为相应的正数按位求反,末位加1即为该负数的补码表示
例:假设机器字长为8位,求-46的补码。
+ 46的补码表示为: 0010 1110
按位求反: 1101 0001
末位加一 1101 0010
所以,[-46]补码 = D2H
符号扩展:是指一个数从位数较少扩展到位数较多,如从8位扩展到16位,或从16位扩展到32位。
对于用补码表示的数,正数的符号扩展在前面补0,负数的符号扩展在前面补1,假设机器字长为16位,[+46]补码 = 002EH,[-46]补码 = FFD2H。
3.补码运算
在机器里,补码减法是通过对减数求补后把减法转换为加法进行的。符号位参加运算,能自动得到正确结果。
例:假设机器字长为8位,计算25+(-32)
25的补码是0001 1001,-32的补码是1110 0000
结果恰好是-7的补码,可以看出运算是正确的。
例:仍假定机器字长为8位,计算32-(-25)
为把减法转换为加法,要对-25求补,实际上就是25的补码0001 1001, 32的补码是0010 0000
结果恰好是57的补码,运算正确。
摘自http://comic.sjtu.edu.cn/thucs/GD_jsj_019b/text/ch01/section4/khxtf.htm#
4.汇编中会有很多特定的结构与高级语言中的语句相对应,
如最简单的
001 CMP AAA,BBB
002 JNZ 00N
003 ...
...
00N ...
相当于
if(AAA==BBB){003...00M}
001 MOV ESI 00000000
002 MOV EBX 0000000A
003 ...
00K INC ESICMP ESI EBX
00L CMP ESI EBX
00M JL 003
00N ...
相当于
for(int i=0;i<10;i++){003...00J}
001 MOV EDI 00000004 0100
002 AND EAX 00000003 0011 相与后eax为
003 JMP [EAX+EDI]
004 ...
005 ...
006 ...
007 ...
相当于
switch(EAX%4)
{
case 0:004;
case 1:005;
case 2:006;
case 3:007;
}
摘自http://www.pediy.com/bbshtml/bbs5/pediy50503.htm
标 题: 我对菜鸟成长的看法
发信人:afanty
时 间:2003/03/21 07:27pm
详细信息:
5.movcx
MOVSX r16,r/m8 0F BE /r 不影响标志位 带符号扩展传送指令
MOVSX AX, BL
MOVSX r32,r/m8 0F BE /r MOVSX EAX,BL
MOVSX r32,r/m16 0F BF /r MOVSX EAX,BX
6.%lu-%lx是什么意思?
C语言输出不同类型的整数,需要使用不用的格式限定符
输出 unsigned int 类型的整数,要用 %u 。输出 long ,要用 %ld;如果要以十六进制或者八进制形式输出,那就用 %lx(或者%lX)或者 %lo。注意:虽然整数常量的后缀使用大写或者小写英文字母都没关系,但是它们格式限定符必须使用小写!如果我们要输出 short 类型的整数,可以在 %d 中间加上前缀 h,也就是%hd;同理,%ho 和 %hx(或者 %hX )分别表示以八进制或十六进制形式输出。前缀 h 和 l 可以和 u 组合,表示输出无符号整数。例如:%lu 表示输出 unsigned long 类型的整数;%hu 表示输出unsigned short类型的整数。如果您的编译器支持C99,可以使用 %lld 和 %llu 分别表示输出 long long 和 unsigned long long 。
所以是长无符号型 十六进制长整型
摘自http://cpp.ga-la.com/html/1/2/0510/27.htm
7.参数传递
;========================================注册失败消息================================================
004011EF 6A 10 push 10
004011F1 68 E4204000 push Crackme1.004020E4 ; ASCII "Nope"
004011F6 68 E9204000 push Crackme1.004020E9 ; ASCII "Try again"
004011FB FF75 08 push dword ptr ss:[ebp+8]
004011FE E8 34000000 call <jmp.&USER32.MessageBoxA>
00401203 C3 retn
;========================================注册成功消息==================================================
00401204 6A 40 push 40
00401206 68 D2204000 push Crackme1.004020D2 ; ASCII "Solved"
0040120B 68 D9204000 push Crackme1.004020D9 ; ASCII "Well done."
00401210 FF75 08 push dword ptr ss:[ebp+8]
00401213 E8 1F000000 call <jmp.&USER32.MessageBoxA>
00401218 C3 retn
;======================================================================================================
可以看出在调用<jmp.&USER32.MessageBoxA>之前有压栈动作,也就是通过堆栈传递参数。(本人不会win32汇编,悟出这一点,让行家见笑了)
我找到了一本win32api详解(http://www.pediy.com/Document.htm可下载)。上面是这样讲的
int MessageBox(
HWND hWnd, // handle of owner window
LPCTSTR lpText, // address of text in message box
LPCTSTR lpCaption, // address of title of message box
UINT uType // style of message box
);
所以参数是倒着压栈的。
8.
F2:设置断点,只要在光标定位的位置(上图中灰色条)按F2键即可,再按一次F2键则会删除断点。(相当于 SoftICE 中的 F9)
F8:单步步过。每按一次这个键执行一条反汇编窗口中的一条指令,遇到 CALL 等子程序不进入其代码。(相当于 SoftICE 中的 F10)
F7:单步步入。功能同单步步过(F8)类似,区别是遇到 CALL 等子程序时会进入其中,进入后首先会停留在子程序的第一条指令上。(相当于 SoftICE 中的 F8)
F4:运行到选定位置。作用就是直接运行到光标所在位置处暂停。(相当于 SoftICE 中的 F7)
F9:运行。按下这个键如果没有设置相应断点的话,被调试的程序将直接开始运行。(相当于 SoftICE 中的 F5)
CTR+F9:执行到返回。此命令在执行到一个 ret (返回指令)指令时暂停,常用于从系统领空返回到我们调试的程序领空。(相当于 SoftICE 中的 F12)
ALT+F9:执行到用户代码。可用于从系统领空快速返回到我们调试的程序领空。(相当于 SoftICE 中的 F11)
摘自:http://bbs.pediy.com/showthread.php?t=21284
[注意]看雪招聘,专注安全领域的专业人才平台!