滴水逆向培训基础教程_第1页
滴水逆向培训基础教程_第2页
滴水逆向培训基础教程_第3页
滴水逆向培训基础教程_第4页
滴水逆向培训基础教程_第5页
已阅读5页,还剩240页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

前2008年滴水公司成立之日起,我们就着一个非常严峻的现实,巨大的工作量无人1首先介绍一下滴水逆向培训的主讲老师-唐老师。2000年毕业于西北一所不知名的大学,贸易经济专业毕业—似乎资深的程序员大多非计算机专业出身。有着10年以上的编程经VT调试器的开发者,成功逆向虚拟机VMWare、加壳软件Themida和VMProtect,并即将完让无法参加实地培训又渴望学习的人一起我们的经验。貌,本采用+章节体的风格编辑整理而成。先引述唐老师的讲课内容,然后再添加于编写的时间过于仓促,本身可能存在诸多错误,希望读者多多批评指正,在后下坚实的基础。培养独立的能力。你初中数学优异基本就可以证明具备一定的逻辑思维能力了。二是有;是最好的老肯用功;即使你的智商超过也不能确保你一定成绩优异,天才+勤奋才是成功的秘有有育已本识体的求本没有以打《滴水逆向培训基础》参考,更为详尽前 第一章进 引言 数据进 本节主要内容 老唐 课后疑问 课后总结 课后练习 进制运 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 十六进制与数据宽 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 逻辑运 课后理解 课后疑问 课后总结 课后练习 第二章寄存器与汇编指 引 通用寄存 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 内 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 汇编指 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 EFLAGS寄存 课后理解 课后疑问 课后总结 课后练习 第3章C语 引 C的汇编表 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 函 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 内存结 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 条件执 课后理解 课后疑问 课后总结 课后练习 移位指 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 表达 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 if语 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 循环语 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 变 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 数 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 结构 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 switch语 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 define与 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 指 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 结构体指 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 第四章硬编 引 定长编 本节主要内容 老唐 课后理解 课后疑问 课后练习 不确定长度编 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 其他指令编 本节主要内容 老唐 课后理解 课后疑问 课后总结 课后练习 第五章保护模 引 段寄存器结构 本节主要内容 老唐 课后理解 课后总结 课后练习 段寄存器结构 本节主要内容 老唐 课后理解 课后疑问 课后总结 段寄存器结构 本节主要内容 老唐 课后理解 课后总结 课后练习 段权 本节主要内容 老唐 课后理解 课后总结 课后练习 调用 本节主要内容 老唐课后理解 课后总结 课后练习 其他门描述 本节主要内容 老唐 课后理解 课后总结 课后练习 本节主要内容 老唐 课后理解 课后总结 本节主要内容 老唐 课后理解 课后总结 课后练习 关键 本节主要内容 老唐 课后理解 课后总结 课后练习 2-9-9-12分 本节主要内容 老唐 课后理解 课后总结 课后练习 控制寄存 本节主要内容 老唐 课后理解 课后总结 课后练习 第六章PE(略 第七章C++(略 第八章操作系统(略 开始学习本之前,请您务必先仔细阅读《前言》,将会对您接下来的学习有所帮助第一引言我们为什么要学习进了,只留下十进制,这一章主要是带我们了解各种进制,找回应有的。本章必须要掌握的知识本章常犯的错误数据进本节主要老唐现在请一个同学上来写出10进制的0-0235689say:101个数say十进制从0100十进制是由、、、、、、、、、十个符号组成,逢十进一。0,最大是8,进一。练习用九进制写出十进制的101个元素0123456710101112131415161710110310410610711111311411611706,逢七进一。用七进制写出十进制的101个元素02356160160161162163164165200201XA也行,共十一个符号组成,最小是0X(A),逢十一进一。练习:用十一进制写出十进制的101个元素0235689A练习用三进制写出十进制的101个元素0110112021220220221比如:2+24各种进制如表1-表1-1:1-11进制表123456789进制其实是N种符号组成的课后疑问课后总结进制是由元素组成的,N进制就是有N个元素组成,逢N课后练习在纸上用1到16进制分别描述100写一到十六进制,0-0到16进制,每个进制写100个数进制运本节主要老唐NN进制都会,唯独不会练习那现在我们给N进制下个定义:N进制就是由0、1、2、3、4……N-1共N个符号组成,逢N进一练习小刘say:“后面咋整?”say:“随便。”say:“是啊。”其实我们学到0,1,2,3,4,5,6,7,8,9是人的符号。零,一,二,三练习用二进制从零写到十进制的100010100110练习765-练习练习1*1=1*1=2*1=12*1=23*1=33*2=122*1=23*1=33*2=114*1=44*2=134*3=222*1=23*1=33*2=104*1=44*2=124*3=205*1=55*2=145*3=235*4=321*2=21*3=32*3=61*4=42*4=113*4=151*5=52*5=133*5=214*5=261*6=62*6=153*6=244*6=335*6=422*1=23*1=33*2=64*1=44*2=84*3=135*1=55*2=115*3=165*4=226*1=66*2=136*3=206*4=266*5=337*1=77*2=157*3=237*4=317*5=387*6=468*1=88*2=178*3=268*4=358*5=448*6=538*7=622*1=23*1=33*2=64*1=44*2=84*3=105*1=55*2=a5*3=135*4=186*1=66*2=106*3=166*4=206*5=267*1=77*2=127*3=197*4=247*5=2b7*6=368*1=88*2=148*3=208*4=288*5=348*6=408*7=489*1=99*2=169*3=239*4=309*5=399*6=469*7=539*8=60a*1=aa*2=18a*3=26a*4=34a*5=42a*6=50a*7=5aa*8=68a*9=76b*1=bb*2=1ab*3=29b*4=38b*5=47b*6=56b*7=65b*8=74b*9=83b*a=92b*b=101课后理解say:我们可以通过十进制的乘法,从中摸索出规律我们把七进制的乘法表写出来=1=2=1*2的基础上加2=?在2*2的基础上加这样,乘法演变成加法。所以很快得出七进制的乘法表=1=2=4=3=63*3==4=113*4===5=133*5==265*5=6=153*6==335*66*6=课后疑问111-111=有的人说等于0。那么,如果我使用0作为一进制的符号00+000=000-00=000000其实我们不用纠结于算数的结果,111-111空,这个空可以用其他符号代替,只要不课后总结任何一种进制,他自身就是一个完美的体系结构,可以直接加减乘课后练习对照9*9乘法表,建立6*6乘法表将16进制的元素用2进制的元素下把16进制的元素和二进制对比,发现其中的十六进制与数据宽本节主要老唐长。32位,已经很大了,4个G。我们说人类特别喜欢用十进制去写。比如256,使用二进 B,B来表最多只有八种,那我们用A,B,C,D,E,F,G,H,去表示。010在这是C是吧。111是H是吧,010C,101F010C,CFCHC。那好了,我们也可以同理,我们照样1000,1001,1010,1011,1100,1101,1111,I,J,K,L,M,N,O。不需要排顺序是L,1010是K,0010是C,CKCK。导致多位多位的书写。整体变得很短了。问题就是个符号。三位三位书写八个符号。四位四位书写16个符号。五位五位书写32个符号。A00。这两种书写形式表示的含义是一样的。上面是书写形式,下面是本质形式。当然你也可以一位一位的书写,我用A表示0,B表示1,就是BBABBAAA……这也是二进制的书写形式。你可以另外定义两个符号,未必要用用原来的01。另定义两个符号用AB两个符号。也可以两位两位的书写,用ABCD来表示。或者是三位三位的书写。其实很简单。就是因为在全世界数字的符号最简单,我们就不应该用ABCD这个11位,22334455位书写呢,了。所以要大于三位三位的书写。因为我们不要浪费这个符号。就使用四位四位的书写,才能保证把人的符号全部用上。那四位的书写,少了几个符号,那用谁的符号补上去。毕竟英国人没有古人聪明,我们补太多的符号,不便于,所以使用四位四二进制从0000写到1111然后改成16个符号如果按照这种新的书写方式,那发现如果要进位的话,要满16才进位。中国古代就015,下面加上150,15。这就是最早的计算机。有的银行现在仍然使这里为了书写方便我们只写8个位-1=0--例:从0,写到-50。说明:见图1-1:图1-1:计算机宽课后理解在数算中,数值的大小(即宽度)是没有限制的,比如进行运算.比如给定的一个数0xABC,如果规定它的宽度为32位(32通常是二进制的32位,那么该数值的有效值为0x56789ABC.如果运算结果超过其宽例:设给定的数值宽度为8(二进制则可以表示的最大值为0xFF(B。此时,0x81+0x8010000001B10000000B=100000001(B)00000001图1-2:计算机数值宽如上图所示,字节(Byte)占8位二进制宽度;字(Word)占据16位二进制宽度符号类型时,最作为符号位,最为1,表示负数,反之为正数,见图1-3:有符号数值大小,见表1-2:表1-2:有符号80x80(-0x7F(27-0x8000(-0x7FFF(215-课后疑问课后总结计算机是定宽的课后练习2,4,16进制,每进制最大32位,写出8逻辑运本节主要VC++6.0老唐比如111111111111逻辑运算中只有错与对,成与败两个结果(也就是0和1。1+1=1(1+1=2不等于0,就是0-1-0-1-电路如图1-1-4:OR运算与等效与运算电路如图1-5:1-5:AND运算与等效异或运算电路如图1-6:1-6:XOR运算与等效与运算:比如一个家庭,只有丈夫和妻子都有能力,才能有孩子。File->new,弹出下面窗口,点击Win32ConsoleApplication,然后在Projectname框中填入工程名,例如“ oWorld”,点击OK,如图1-7:图1-7:新建工程在图1-8中选择第三项:“A’ o,world’application”,然后点击1-8:win32Comsole图1-9:寄存器窗movecx,0x124}课后理解say:或运算(|)只要有一个是1,就是1,其它为异或运算(^)同的为0,不同的为1say:课后疑问课后总结二进制实现了逻辑运算和算术运算的统课后练习1.2、4、6进制,每个进制写32位。0-2.10个寄存器,背熟顺第二章寄存器与汇编指引想要了解计算机,首先要了解的便是cpu,cpu是计算机最的部件,因为计算机的所有指令都是由cpu处理,而cpu的部件之一是寄存器。这一章我们就来认识一下寄本章必须要掌握的知识8、16、32位通用寄存溢出标志位(OF)的理pop与push指令的理通用寄存本节主要8/16/32位通用寄存老唐主要记住这8个寄存器:mov指令可以任意移动这8个寄存比如:addeax,ecx还可以是一个数,只要保证是32位即可。 个寄存器是分段的。比如算盘,我们可以只用一半,或者四eax可以分成四部分:eax0-31,其0-7位叫AL,8-15位叫做AH0-位又称为AX。AL:low;AH:high。ecx,edx,ebx也是一样的,如图2-1ESP,EBP,ESI,EDI,这四个寄存器只分成两段,比如ESP整体0-31位称为ESP,0-15位称为SP。通过以上,我们可以看出,32位的寄存器8个:EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI,每个寄存器都有一个编号:0号,1号,2号,3号……还有16位的寄存器:表2-1:寄存器编编号(二进制编号(十进制321680123456732位寄存器有自己的编号,16位寄存器也有属于自己的独立的编号。当然,他们叠的,当改变了32位的寄存器,相应的16位寄存器也会跟同样,也有8位的寄存器,第0号AL,第1号,CL,DL,BL,AH,CH,DH,BH。顺序不能乱。当然还有两个寄存器:EIPEFLAGS(又称为EFL,89号寄存器,EIP16位,叫做IP。EFL16FL。这两个寄存器使用相对较少。练习而不可以是XORAL,BX。后面的寄存器可以改成立即数。课后理解cpu常用的寄存器。In手册给出了通用寄存器的功能:通用目的寄通用寄存器结构见图2-图2-2:通用寄存器结早期的技术还没有现在成熟时,8个通用寄存器宽度是8位(这里指的是二进制的8位:AL,AH,CL,CH,DL,DH,BL,BH。后来cpu技术逐渐发展,由8位发展成16位,于是寄存器由8位演变成16位:AX,CX,DX,BX,SP,BP,SI,DI。但是为了兼容前面的8位技术,将之前的8个8位寄存器封装到AX,CX,DX,BX寄存器中。技术发展的步不会停歇的,之后将16位寄存器都扩充了一倍,于是32位寄存器出现了,当然这里截至32位,64位和128位寄存器留给大家思考32位通用目的寄存器的指定用途如·EAX:累加器·ECX:计数·EDX:I/O·EBX:DS段的数据指·ESP:堆栈(Stack)指·EBP:SS段的数据指·ESI:字符串操作的源(Source)指针;SS段的数据指·EDI:字符串操作的目标(Destination)指针 段的数据指课后疑问回答:cpu具有判断指令长度和预处理指令的功回答:其实我也想,可是In 课后总结汇编就是在“寄存器与寄存器”或者“寄存器与内存”之间来回移动数课后练习32,16,8movaddANDsuborxornot内本节主要寄存器,老唐的只做了8个:EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI。内存速度慢,很便宜,所以数量位的。这也是我们现在的计算机叫32位计算机的主要原因。如果按寄存器的宽度是位的话,是不对的,因为还有很多寄存器是大于32位的。我们通用的8个是32位的内存地址是固定的32位。以前的计算机之所以称为16位计算机,就是因为他的内存单编号是16我们学过的指令MOV,能操作寄存器和内存office等一些大型软件。,SUB(,XOR(,OR(,AND(其 ADD……这些也是移动指令:把源加上目标然后移动到目标操作数里面去有byte是一个字节,dword是节。其实[]里面不但可以写具体的一个数,还可以写某一个寄存器的第一个寄存器叫做BASE寄存器(8个寄存器都可以第二个寄存器是INDEX也是82次方,23次方,后面再加一个数(DISP。 eax,ds:[0x401000+8*eax+eax];这个可以执行吗cpu实现了将地址赋给LEA指令把方括号里面内存的编号给目标寄存器:loadeffectiveaddress。当一个值不好确定宽度时,使用dwordptrwordptr,byteptr,源可以是表明干什么。复杂的指令也是由简单的指令组合而成。课后理解之一,宽度为8位。见图2-3:图2-3:内存格如图2-3,为了区别内存和cpu内部的寄存器,内存中的寄存器打上“[]”,专业术语称之为“地图中的内存大小从0到0xFFFFffff,也就是说有0xFFFFffff个内存寄存器存在,内存地址从0-0xFFFFffff。注:此处0xFFFFffff写法为何不十六进制不区分大小写,这样写是为了便于识别,我们可以很清楚的看出有8个F。内当用户运行程序时,cpu需要不停地去从区取代码和数据,这样非常耗时,于是将32位数 存入内存中的0x12FFB8地址处说明:我们从图2-4可以看出:数值的在内存地址中的图2-4:内存方内存地址的表示方法有哪些·位移 ·比例因子(ScaleFactor)1,2,4下列五种地址模式为常用组合(图2-3··(·(索引×比例因子)图2-5:偏移(有效地址)计算极有可能的原因是(猜测u的技术员们只好订个规矩:只能使用五种表示方法,否则一律不识别。练习1.[0x234791]//vc6不支持注:reg表示通用寄存器课后疑问如果算出的内存地址结果超过32位会怎样回答:如果结果超过32位溢出,则计算机只取32课后总结内存的通用格式:reg+reg*数+立即课后练习练习复杂地址表达形式的操作如lea[eax汇编指本节主要汇编语言的基础指令(push、pop、老唐mov[esp],eax使用vc6调试观察内存的变化moveax,[esp]练习VC6gotodisassmbly,一步一步运行,并观察eip变化。其实eip一直在变化。在80x86CPU中,eip寄存器指向的是将要执行代码的位置, moveax,0xxchgeax,eax又称为nop。盘的人在哪里,在内存中的哪个位置)。eip是寄存器,所以他的值可以被改变。每个地方都可以取个,如:lab:movmovecx,offset既然汇编指令就是在寄存器和内存间移动指令,那么我们可以使用mov来修改eip:moveip,寄存器/立即数简写为(取别名jmp寄存器/立即数pushoffsetlabmoveip,eaxlab:...calllearetIW,比如ret0x4课后理解·PUSH:压入堆栈,见图2-图2-6:PUSH指令图subesp,4·POP:弹出堆图2-7:POP指令图然后堆栈加节。POPeax可以简化成:addesp,4;课后疑问POPESP是否也可以简化为指令方式?说明:如果按上述的则写成addesp,4;可以看出,第一条汇编指令中得到的esp值被第二条指令修改,所以直接将esp带入是错误的。因为popeax又可以等价于:addadd课后总结操作和运算本身也是代码,并存在于内存中课后练习以下代码在纸上抄写10遍(目的抄会PUSHDWORDDS:[ESP-PTR POPERX 做各种测试;单步执行语句,查看寄存器和内存的变化,且写出规EFLAGS寄存本节主要熟知标志寄存器的各种运算对于CF,PF,AF,ZF,SF这些标志位的影老唐下面我们开始讲标志寄存器EFLAGS,如图2-图2-8:标志寄存两个数相加,如果最向进位,结果忽略这个位,那么这个位要放到CF里面减法运算,如果最向借位,则CF位为1位暂时放在标志寄存器里面的一个位CF,以后有待查证,减法同理。CFeflag里面第0位。运算的宽度可以自定义:可以是8位,16位也可以是CF如果本身是零,运算后无进位,则CF还是零,其实CF被改了,只是结果没有变第一位没有使用,是1看结果(这里指二进制,parityflag,EFLAG中的第二位。AF位:看低四位加减是否有进/借位,AF置1。没有进/借位也会改AF(置SF位,最是多少,就置多少,是最的品,没有其他含义,如果是8位运7位,1615位,3231位(0位开始。 位:最相同,看次是否向最进位,最不同,无溢出 :最的进位与次的进位异或movdwordptr[EDI],dwordptr[ESImovsdmovwordptr[EDI],wordptr[ESI]movswmovbyteptr[EDI],byteptr[ESI]movsb练习movedi,0x427c20movesi,0x427c48EFLAG里面有一个DF位,movsb/w/d每移动一次数据,都要对ESIEDI进行加1/2/4,或减1/2/4,到底是加还是减,看DF位,当DF1时,是减,当DF0的时所以我们使用std(setDF)DF1,cld(clearDF)DF0,观察指令DF影响的其他指令有课后理解标志寄存器(EFLAGS)又称为程序状态和控制寄存器(ProgramStatusandControlRegister,主要用于记录当前的程序状态。(CF例:定义数值宽度为32位,则0xFFFFffff+2在运算过程中出现进位PF例:运算结果0x4567中1的个数8个1,PF=1。(ZF(SF(IF(DF从高地址到低地址置1(STD和CLD指令设置和清除该标志位。始还是从高地址开始,置1表示由高到低,置0则反之。·溢出标志(OF):运算结果溢出置1。区别于进位标志(在运算过程中。在这里要用 汇编语言程序设计中的一段话:CPU是如何检测溢出的:在加法和减法运算完后 使用一种非常有趣的方法确定溢出标志的值运算结果最高有效位向的进位(CF)与到最高有效位的进位值异或,其结果放到溢出标志位例如8位二进制数 无进位,但第7位向有进位值(CF=1。如图2-9:1XOR0=1of=1。课后疑问课后总结标志寄存器主要是记录当前的程序课后练习3C引在了解了汇编语言后,我们开始学习C语言,虽然两者看上去没什么关系,但是所有编译器都是先将高级语言(包括C)转换成汇编,再由汇编转换成二进制。而且汇编语言语法简单,可以解释所有C语言中的语法。有人可能疑惑:既然汇编语言语法简单,为什么可移植性差。以往我们学习C语言总是和汇编扯不上半毛钱关系,这样理解的错特错,接下来我们通过汇编来揭开C语言神秘的面纱。本章必须要掌握的知识汇编与C本章常犯的错误C的汇编表本节主要汇编与C老唐declspec(naked)intabc(inta,int{popedipopesipopebx}intr;在r=abc(2,3);处下断点然后按F5,再按F11单步观察指令运行比如3-表3-1:内存地址书写2>现在修改declspec(nakedintabc(inta,intb)里面的内容如下:pushebxpushesipushmovmovecx,[esp+0x14]addeax,ecx然后单步调试并观察变化。为什么最终打印的结果是5,并将修改的内存画在纸上。3>修改declspec(nakedintabc(inta,intb)大括号里面的内容如下:pushebpsubesp,4pushebxpushesipushedimoveax,[ebp+8]mov[ebp-4],eaxpopedipopesipoppopebp修 abc(2,3)为其他整数比如,abc(10,2),观察结果变化4>修改declspec(nakedintabc(inta,intb)大括号里面的内容如下:pushebpmovebp,esppushebxpushesipushedimovecx,0x11leaedi,[esp+0xc]repstosdmoveax,[ebp+8]mov[ebp-4],eaxpopedipopesipopmovesp,ebppopebpintabc(inta,intb,intb,intc写在一行和写在三行是一回事。*/{return}a=2;变量(内存单元所以说,给每一个算盘取一个名字,比如:inta,intb,intc,intr,无论你取什么名字,都会分配给你节的内存,然后在这个算盘上赋值,赋值很简单。我们称a=2;变量(内存单元不需要看C,看汇编如何显示课后理解其中数据类型即数据宽度 语言定义了以下几种数据类型int:32位char:8位注 语言除了十六进制数外,其他语句都区分大小写,这一点区别于汇编我们现在用实例来说明一个完整的C程序使用VC6打开并创建一个控制台的 #include<stdio.h>intmain(void)/*程序{num=1;/*赋值语句:num值为1*/ return0;/*返回*/}1〉首先我们要了解的是函数,即我们的程序从哪里开始运行:main函数。注意一个新名词:函数。函数的英文名是function,它的原意是功能、作用,所以“main函数”2〉那我们第一条执行的指令是:intnum;申明语句,该条语句给了我们三条信息:该变量名字是num;宽度是32位;C语言的每一条语句后都要以”;”结尾。3〉第二条语句:num=1;给该变量赋1。既然num是变量,那么它的值可以再次被4〉使用(专业术语是调用)一个printf函数,printf译为打印,所以我们可以说调课后疑问declspec(naked)代表什回答:代表函数,不要编译器帮我们构造函数框架,用户自己构造课后总结申明变量(比inta)就是给内存取名课后练习函本节主要C语言函数的定老唐intabc(inte,intf,intc,inta,int1个),取个名字,作为标识符,可以取一排变量,用逗号隔开,最后没有//然后大括{inty;returnx+y+a;}因为这个导致产生一个CALL。然后在调用的时候可以发现,他会往内存里面写参数你在括号里写一个3,他会push3。在括号中定义多少个,他就会在往内存单元写多少个数,和他对应的是,从右边往左边开始,先给右边的赋值,所以在高地址,因为push指令会令会导致esp-4,所以最右边的是地址是最高的内存单元。比如:调用abc(1,2,3)的汇编程序如下321每一个名字(变量)都对应一个4字节的内存单元。比如:intabc(inte,intf,intc,inta,intb)汇编程序如下: edi,[ebp- 是圆括号的里面定义的名字,还是大括号里面定义的名字,我们都把他叫做变量a=3;(variaba=3; 语言中的回车符只是为了便于阅读。将所有语句并做一行,代码仍然可以运行r=abc(1,2,3);修改为:{submovdwordptrds:[esp+0],1movdwordptrds:[esp+4],2movdwordptrds:[esp+8],3callabcaddesp,0xcmovr,eax}课后理解{}intAdd(inta,int{intc=a+b;}intresult=这样就实现了34+56的和,并把这个结果传给了result课后疑问课后总结函数格式:前面是 int,后面是个名称、左圆括号和右圆括号课后练习内存结本节主要老唐intabc(int{inta;intb;int}写的多了,自然就清楚了,在汇编里写一个call,或者在C语言里,main函数中写一个函数名,左圆括号,参数,右圆括号,然后call指令地址加上本指令的长度就是下一条指令的首地址,放在内存里面去,如图3-1:图3-1:调用函数内存练习intabc19(inta,intb,intc,intd,int{return}intabc5(inta,intb,intc,intd,int{intr;intv=abc6(a+5,b+5,c+5,d+5,e+5);r=a+b+c+d+e+v;return}intabc4(inta,intb,intc,intd,int{intr;intv=abc5(a+5,b+5,c+5,d+5,e+5);r=a+b+c+d+e+v;return}intabc3(inta,intb,intc,intd,int{intr;intv=abc4(a+5,b+5,c+5,d+5,e+5);r=a+b+c+d+e+v;return}intabc2(inta,intb,intc,intd,int{intr;intv=abc3(a+5,b+5,c+5,d+5,e+5);r=a+b+c+d+e+v;return}intabc1(inta,intb,intc,intd,int{intintv=abc2(a+5,b+5,c+5,d+5,e+5);r=a+b+c+d+e+v;return}intabc(inta,intb,intc,intd,int{intr;intv=abc1(a+5,b+5,c+5,d+5,e+5);r=a+b+c+d+e+v;return}main函数中的调用语句intr=课后理解程序PUSH开始RETURN语句结束,再将返回值写入EAX传递给下一函数使用。课后疑问课后总结函数调用都会CALL指令的执行课后练习条件执本节主要Jcc、SETcc、CMOVccif老唐eaxebx后面两cc表示可以替换。比CMOVCeax,edx表示当CF1时,数据从edx到eax。如果CF为0时,这条指令什么都不做,也就是说在移动数据时,首先要判断标志位;外还p、np,z、nzCMOVcceip,”等于“Jcc”,Jcc也有16种写法。所有条件见3-2:表3-2:Jcc(CF+ZF)=高于/不低于等CF=高于或等于/不低CF=低于/不高于等(CF+ZF)=低于或等于/不高CF=ZF=等于/CF=ZF=不等于/PF=PF=CX=寄存器CXECX=寄存器ECX((SF^OF)+ZF)=大于/不小于等(SF^OF)=大于或等于/不小(SF^OF)=小于/不大((SF^OF)+ZF)=小于或等于/不大OF=SF=OF=SF=当CF=0时,AL=0。练习注:cc代表十六种条件,十六种写练习intfun10(inta,intb,intc,intd,int{intsum;intstub;return0;stub=sum=stub+a+b+c+d+e+(a+5+b+5+c+5+d+5+e+5);returnsum;}调用语句:result课后理解cmovcedx,eaxcf=1等同于movedx,eax如果cf=0,不处理cmovncedx,eaxcf=0movedx,eaxcf=1,不处理setccoprd:oprd可以是8bit寄存器、内存,不可为立即数setzal:zf=1,al1zf=0,不处理setnzal:zf=0,al1zf=1,不处理课后疑问课后总结条件执行指令是根据EFLAG寄存器中相应的标志位为判断条课后练习移位指本节主要老唐ADD、SUB、ADC、SBB、OR、XOR、AND之外,总会有其他指是不改变目标操作数SUBeax,edxeax的值减去edx,结果放到eax里面去,影响标志位,而cmp只影响标志位,运算结果忽略,不影响eax。SHRAL,2向右面移两个位,如果AL值 ,则向右移动两位后变 如图3-2:3-向左移:SHL,只要会移动一位,移动N位就明白了,移动后的结果放在目标寄存器里面,当然该操作也会改变标志寄存器中的CF,将移出来的位赋给CF;右移也是一样,凡是移出来的那个位都赋给CF,如图3-3-疑问:如果N位,哪一位赋给移动N位,相当于N次移动一位,也就是说,每移动一位,就将移出来的那一位CF,移动了N位,就赋给CFN次。所以结果很明显,就是最后移动的那当然移位指令照样影响SF位:将移动后剩下的最赋给SF。还要看结果是否全为零,如果全为零,ZF10PF位(1的奇偶性OF位。果最补0,是逻辑移位;最保持不变(符号是算术移位,如图3-4:3-SAR:算术右移,A是算术arithmetic。RCL和RCR:带进位的循环移位(C代表CF位循环左移一位,将最给课后理解ROL/ROR如图3-3-RCL/RCR如图3-3-课后疑问C语言中移位指令的书写格式左移<<,右移>>左移只会生成SHL指令,因为SHL和SAL等无符号右移(>>前的数)会生成SHR,有符号数右移会生成课后总结算术移位涉及符号位的运算,而逻辑移位不涉课后练习画出下列指令执行时内存数据的变化情况intCumulativeHundred1(inta,intb,intc,intd,inte,intf,intg,inth,inti,intj);intCumulativeHundred7(inta,intb,intc,intd,inte,intf,intg,inth,inti,intj){intsum;f+20,g+20,h+20,i+20,j+20);sum=stub+g+h+i+j+((a<<1)+10+(b<<1)+10+(c<<1)+10+(d<<1)+(e<<1)return}intCumulativeHundred6(inta,intb,intc,intd,inte,intf,intg,inth,inti,intj){intsum;stub=(a>=90)?0:CumulativeHundred7(a+20,b+20,c+20,d+20,f+20,sum=stub+f+g+h+i+j+((a<<1)+10+(b<<1)+10+(c<<1)+10++10return}intCumulativeHundred5(inta,intb,intc,intd,inte,intf,intg,inth,inti,intj){intsum;f+20,g+20,h+20,i+20,j+20);sum=stub+e+f+g+h+i+j+((a<<1)+10+(b<<1)+10+(c<<1)++10return}intCumulativeHundred4(inta,intb,intc,intd,inte,intf,intg,inth,inti,intj){intsum;f+20,g+20,h+20,i+20,j+20);sum=stub+d+e+f+g+h+i+j+((a<<1)+10+(b<<1)+10+(c<<1)+10+d+10+e+10+f+10+g+10+h+10+i+10+j+10);return}intCumulativeHundred3(inta,intb,intc,intd,inte,intf,intg,inth,inti,intj){intsum;f+20,g+20,h+20,i+20,j+20);sum=stub+c+d+e+f+g+h+i+j+((a<<1)+10+(b<<1)+10+c+10+d+10+freturn}intCumulativeHundred2(inta,intb,intc,intd,inte,intf,intg,inth,inti,intj){intsum;stub=(a>=90)?0:CumulativeHundred3(a+20,b+20,c+20,d+20,e+20,f+20,g+20,h+20,i+20,j+20);sum=stub+b+c+d+e+f+g+h+i+j+((a<<1)+10+b+10+c+10+d+ereturn}intCumulativeHundred1(inta,intb,intc,intd,inte,intf,intg,inth,inti,intj){intsum;f+20,g+20,h+20,i+20,j+20);sum=stub+a+b+c+d+e+f+g+h+i+j+(a+10+b+10+c+10+d+f+10return}表达本节主要老唐cmp和SUB指令功能是一样的,只是cmp不改变目标操作数的值,同样影响标志位。AND的功能是按位与。TEST与AND的功能相同,只是不改变目标操作数的值,也同样影响以后我们不需要写汇编,只需要看懂别人写的汇编代码即可。前面提到,定义一个C+……表达式的定义:凡是由变量、常量和算术符号起来的都可以称为表达式有圆括号,中括号和大括号,在C语言中只有圆括号。int_abcd(intab,intcd,int{intdc;baab+cd;//}练习注:int是有符号整型,unsignedint是无符号整型。intabc(inta,intb,int{inth;intj;var=0;var=(var,0x5,var+0x5);//var=var+0x5;return0;}单目/双目/三目运算符:b=b+c等价于b+=c计算机做有符号乘法(IMUL)时,首先判断最是否为1,为1(负数)时,将101后的数(此时为正数0减去结果。当做乘法时,目标操作数默认为EAX或EDX:通常乘使宽度扩大一倍,8位的乘法需要两个字节保存,32位的乘法64位保存。1个字节相乘时,结果放在AX里面,两个字节相乘时,结果放在EAX里面,4个字节乘法时,结果放在EAXEDX里面,其中EAX为。比如MULecx;将ecx乘以eax并将结果放在EAX和EDX中。除法里面,结果放在EAX里面,余数EDX里面EAXIMULECX,EAX,则结果会溢出,没有意义。比如:-5*-61*(0-(-5)*1*(0-(-6))练习写出下列C程序对应的汇编代intabc(inta,intb,int{intv;intv=a+b+c;r=a|b&c;}intab(inta,intb,intc,int{intv=abc(a+b,b+c,c+a)+3;returnv+d+5;} repstos dwordptr[edi][bp4][ebp-8[ebp+4] 练习写一个函数,实现只有表达式由编译器生成汇编,其他部分由自己构造(汇编实现说明:在写函数前需要在函数前加declspec(naked):declspec(naked)abc(inta,intb,intc){intv;intr;{pushebp;subesp,LOCAL_SIZE(编译器的宏)//}{moveax,rpopebp}}课后理解1.2.+、-、*、不等号符号:==、>=、<=、!=课后疑问数字3是表达式吗课后总结凡是由变量、常量和算术符号起来的都可以称为表达式课后练习int#33;inta;int2a;inti;int{intv;inta;v+=i++++;v+=return}if本节主要if语句的书写格ifelse老唐shppintabc(intab,intcd,intef)//ebp+0:ebp{intv;//ebp-4inth;//ebp-8intr;}{//可以写任意多个表达}既然if语句中间可以放任意语句,if语句也属于语句,那么if语句中间也可以if语句if{if{}}if语句的第二种格式if{}{//也可以是任意语}if语句的第三种格式if{//可以是任意语}else{//可以是任意语}else{//可以是任意语}else{//可以是任意语}else{//可以是任意语}说明:逗号表达式也属于表达式,比如if(表达式1,表达式2,……)Jcclab10CMOVcceip,lab10//lab10是其实C语言中也含有功能等价于jmp的指令goto:gotolab10jmpoffset对于if语句,当圆括号里面的表达式值为非0时,执行大括号里面的程序课后理解if(表达式{}elseif(表达式{{}课后疑问可以添加两个else语句,比如{}{}课后总结if语句又称选择语句,用于在可选择的几个动作之间进行选课后练习写出下列函数中FuncMove函数每次执行完后变化内存intFuncMove(intn,intnX,int{intnTemp1;intnTemp2;intnTemp3;nResult=n;nTemp1=0;nTemp2=nTemp3=0;nTemp1|=nY;nTemp2=nTemp2|=nX;returnnResult;}intFuncHanoi(intn,intOne,intTwo,int{intnResult;nResult=1;if(n==1){}{}return}循环语本节主要whilefor老唐5+i++//先进行5+i,再运算4+++i//先运算i+1,再进行;麻烦,所以C语言提供了新的语句while。while()/*圆括号里面可以是任意表达式,表达式的值成立,执行大括号里面的语句{//可以是任意语}练习练习while语句,并调试观察对应的汇编语当while语句中圆括号中值为1时,会执行,while语句里面也可以嵌套{}while();//圆括号里面不能为for语句也是循环语句的一种,for圆括号里面有三个表达不写,则表示为1*/{//可以是任意语}表达式1只在开始时执行一次,表达式2和表达式3每次都执行。执行次序是:1>表达式2>表达式2;//表达式值成3>大括号里面内容4>表达式5>表达式2;//表达式值成6>大括号里面内容7>表达式练习构造for循环语句,观察其生成的汇编代码,并单步观察执行break也是一条语句,通常放在if,whilefor语句中间,作为中断使用,该功能可以由goto语句代替(需要设定。如若break语句处于嵌套循环语句中,则只会跳课后理解For语句可以用if和goto语句实现,实现步 for(;end- for(;end-i+1;{...}if(end-i+1{...{...goto}以上步骤可以说明,c语言中所有句型都可以用ifgotofor语句格式来源forcontinuecontinuefor(的第二个";"(从括号中的第三条语句开始执行课后疑问{{}}回答:lab2,break语句只跳出当前循环。课后总结c语言中所有句型都可以用if和goto实现课后练习intfun(inta,int{{}return}intmain(intargc,char*{intresultfun(1,100);//return0;}变本节主要老唐C语言除了赋值语句外,只有if,while和forintabc(inta,intb,int{int}char表示变量的宽度只有1个字节short表示变量的宽度只有2观察汇编里面出现了movsx和movzx指令操作数0扩展为目标操作数的宽度并赋给目标操作数,如图3-7。图3-7:数值宽度扩intabc(inta,intb,intc)//a,b,c{r=v|a|b|c;//也可以是if,while或for64位(8个字节)时,返回值赋给EDX,EAX*/}4个字节,为什么在计算机里面有个本机尺寸的概念,我们使用的是32位计算机,则计算机对32持比较好,主要类型是32位,cpu针对32位会更快一些。针对其他位数,要进行复杂电路的改变,比如当使用8位时,计算机会先取32位,再掉,只取低位,所以会更期的规则,以本机尺寸为主。所以编译器在对一个字节宽度的变量分配4个字节,使用8位,因为编译器认为本机尺寸会运行更快。所以通常我们在写程序非必通常定义成int,而不定义为char或short因此定义成char{inti=1;//[ebp-j=abc(i,r,j);submovdwordptr[esp],imovdwordptr[esp+4],rmovdwordptr传递参数只是把表达式的值一份,所以子函数abc中使用和修改的只是espesp+0xc位置的值,和ebp-4到ebp-0xc没有任何关系}int{v=abc(a+0,b+0,c|0,d|0);//用汇编实现vabc(a+2,b+2,c|2,d|2);//用汇编实现returnv;}pushmovebp,esp是为了保证函数的稳定voidabc(inta,intb){return;//也可以不写此句,写上更好,代表函数}问题为什么汇编函数头要多减去0x40,要执行subesp,0xXX并赋值intabc(inta,int{intab(...);//如果这个函数依赖ebx,esi,edi}及ebx,esi,edi值保持不变,可以随便改变eax,ecx和edx,并且会在子函数的上方当在函数前使用declspec(naked),自己定义函数结构。declpec(naked)abc(inta,int{{moveax,dwordptr[ebp+0x8]movecx,dwordptr[ebp+0xc]movdwordptr[ebp+0xc],eaxmovdwordptr[ebp+0x8],ecx}}课后理解Movsxmovwithsign-extensionMovzxmovwithzero-extend‘0课后疑问课后总结变量是内存中的一个位置,可以在该位置上值以供程序使用课后练习charsum;chari;sum+=i; al,byteptr[ebp-0x4] al,byteptr[ebp-0x10] byteptr[ebp-0x4],alsum=sum+i;Movsxecx,byteptr[ebp-0x4]Movsxedx,byteptr[ebp-0x10] byteptr[ebp-数本节主要老唐if{v=}{v=}练习找出8个数中的最大intabc(inta,intb,int{inta;//存放最大数}{}v[0]=5;//初始化v[1]=intv[8]char/short/longv[8],ESP减少了多少?intabc(inta,int{inti;score[0]=1;score[1]=score[]=3;//[]里面可以是任意表达式}并观察函数头部subesp,后面的常量变化。v[i]=1;汇编代码表示subesp,0x94//0x40+20*4+4(一个变量movmovdwordptr[ebp+eax*4-subesp,0x58//0x40+20+4(一个变量i)movmovbyteptr[ebp+eax-=======for(i=0i<20i++)//i{v[i]=}当定义一排变量时,比如一个班有5个小组,每个小组有9人,则可以定义int比如一个县有5个学校,每个学校有3个年级,每个年级有

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论