版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
本文格式为Word版,下载可任意编辑——Linux下的汇编与Windows汇编最大的不同就是第一个操作数Linux下的汇编与Windows汇编最大的不同就是第一个操作数1、差不多操作指令
简单的操作数类型说明,一般有三种,
〔1〕马上数操作数,也确实是常数值。马上数的书写方式是“$〞后面跟一个整数,譬如$0x1F,那个会在后面的具体分析中见到大量。〔2〕寄放器操作数,它表示某个寄放器的内容,用符号Ea来表示任意寄放器a,用引用R[Ea]来表示它的值,这是将寄放器集合看成一个数组R,用寄放器表示符作为索引。
b字节值的引用。寻常能够省略下标b。
图1表示有多种不同的寻址模式,一个马上数偏移Imm,一个基址寄放器Eb,一个变址或索引寄放器Ei和一个伸缩因子s。有效地址被计算为Imm+R[Eb]+R[Ei]*s,关于这中寻址方式,我们能够在数组或者结构体中进行对元素进行访问时会用到。操作数类型格式操作数值名称马上数$ImmImm马上数寻址寄放器EaR[Ea]寄放器寻址寄放器ImmM[Imm]绝对寻址寄放器(Ea)M[R[Ea]]间接寻址寄放器Imm(Eb)M[Imm+R[Eb]]〔基址+偏移量〕寻址寄放器(Eb,Ei)M[R[Eb]+R[Ei]]变址寻址寄放器M[Imm+R[Eb]+R[Ei]]寄放器(,Ei,s)M[R[Ei]*s]伸缩化的变址寻址寄放器Imm(,Ei,s)M[Imm+R[Ei]*s]]伸缩化的变址寻址寄放器(Eb,Ei,s)M[R[Eb]+R[Ei]*s]伸缩化的变址寻址寄放器Imm(Eb,Ei,s)M[Imm+R[Eb]+R[Ei伸缩化的变址寻]*s]址图1操作数格式注:操作数能够是马上数值、寄放器值或是来自存储器的值,伸缩因子必需是1、2、4、或者是8。从上面的图我们就能够大致了解操作数的类型了。在操作指令中,最频繁使用的指令是执行数据传送的指令。关于传送指令的两个操作数不能都指向存储器位置〔我的理解是一般存储器存储的基本上地址,不能
够对地址和地址进行操作〕。将一个值从一个存储器位置拷到另一个存储器位置需要两条指令——第一条指令将源值加载到寄放器中,其次条将该寄放器值写入到目的位置。下面给出源操作数和目的操作数的五种可能组合。1、movl$0x4050,êx马上数——寄放器2、movl?p,%esp寄放器——寄放器
3、movl〔íi,ìx〕,êx存储器——寄放器4、movl$-17,(%esp)马上数——存储器
5、movlêx,-12(?p)寄放器——存储器
注意那个地方的指令mov可能有不同的形式,不同平台的汇编一般是有些不一样的,但这并可不能阻碍我们理解汇编,只要熟悉其细节之后就能够明白的。指令效果描述movlS,DD←S传送双字movlS,DD←S传送字movlS,DD←S传送字节movlS,DD←符号扩展〔S〕传送符号扩展的字节movlS,DD←零扩展〔S〕传送零扩展的字节pushlSR[%esp]←R[%esp]–压栈4;M[R[%esp]]←SpoplDD←M[R[%esp]];出栈R[%esp]←R[%esp]+4图2:数据传送指令结合例子来进行讲解一下指令的具体操作,在那个地方将会正式接触到Linux下的GCC开发环境和GDB调试器,只是基本上比较简单的应用。我的Linux操作系统是Ubuntu9.10,其它版本的区别应当不大,
假使我们要编写一个程序,我们能够用Linux下自带的vi或vim编辑器,studyrush@studyrush-desktop:~/C$viexchange.c
vi后面加我们要创立的程序文件的名字,在那个地方是exchange.cstudyrush@studyrush-desktop:~/C$gcc-oexchangeexchange.c
gcc-oexchangeexchange.c或gccexchange–oexchange这两者都能够对源文件进行编译,-oexchange表示对我们要输出的文件名称,可能表达的不够确凿,大伙能够先熟悉一下gcc编译器,应当就会明白的了。
studyrush@studyrush-desktop:~/C$./exchange点加斜线再加输出文件名就表示运行程序,下面是运行的结果。a=3,b=4
使用GDB能够参考附件里面的教程,这份教程写的很不错,看雪论坛本身也有,放在附件里面。
studyrush@studyrush-desktop:~/C$gdbexchange命令disas就表示反汇编〔disassembly〕,后面再加上要显示的函数名,我们就
能够看到函数对应的反汇编代码了。(gdb)disasexchange
Dumpofassemblercodeforfunctionexchange:0x080483c4:push?p0x080483c5:mov%esp,?p0x080483c7:sub$0x10,%esp0x080483ca:mov0x8(?p),êx0x080483cd:mov(êx),êx0x080483cf:movêx,-0x4(?p)0x080483d2:mov0x8(?p),íx0x080483d5:mov0xc(?p),êx0x080483d8:movêx,(íx)0x080483da:mov-0x4(?p),êx0x080483dd:leave0x080483de:retEndofassemblerdump.
进一步来分析上面的反汇编代码,那个地方的代码可能与前面的讲的指令操作有一些不同,由于这是很正常的,不同的操作系统应当有所区别,这也是汇编语言一般与平台有关,移植性并不好。push?pmov%esp,?psub$0x10,%esp
对有过反汇编的人对上面的代码确信可不能陌生,那个地方确实是将ebp进栈,保存esp的值,并为局部变量预留空间。要记得源操作数与目的操作数的位置,前面有讲的。那个地方也一定程度对C语言中的指针使用进行了说明。看源代码能够明白。
mov0x8(?p),êxmov(êx),êx
movêx,-0x4(?p)
mov0x8(?p),êx取得xp,事实上是指针本身,即是地址,汇编表示即可为mov?p+8,êx,那个地方确实是存储器——寄放器的操作方式。mov(êx),êx那个地方是取得指针指向的值,即*xp,(êx)表示取êx中的地址指向的值,譬如寄放器值地址值
êx0x1000x1000xFF
(êx)的值确实是0xFF了。
movêx,-0x4(?p)那个地方是将值赋给局部变量,局部变量是在ebp的上面的,表示其地址比ebp的地址要小。mov0x8(?p),íxmov0xc(?p),êxmovêx,(íx)
那个地方与上面的分析类似,并没有出现局部变量,能够说明那个地方是函数参数在进行交换。那个地方的操作数方式是寄放器——存储器
mov-0x4(?p),êx通过寄放器eax将值返回,记住一般函数的返回值基本上
通过eax寄放器返回的。0x080483dd:leave0x080483de:ret函数返回
分析完反汇编代码之后有没有看出来函数调用是采用哪种调用约定呢?事实上确实是C调用方式〔__cdecl〕的方式。//程序exchange.c,表示交换两个数。#include#include
intexchange(int*xp,inty){
intx=*xp;*xp=y;
return(x);}
intmain(){
inta=4;
intb=exchange(
printf(“a=%d,b=%d\\n〞,a,b);return0;}
通过上面的学习我们能够明白事实上C语言中的指针本质上确实是地址。抓住这一点我们对指针的理解就会更加明白。所以繁杂的指针操作依旧要在实践之中渐渐的把握。
2、算术和规律操作
加载有效地址〔LoadEffectiveAddress〕指令lea实际上是mov指令的变形,由于mov不能够直截了当对两个存储器操作数,,指令将有效地址写入到目的操作数〔如寄放器〕。举个例子:假使寄放器íx的值为x,那么指令lea7(íx,íx,4),êx将设置寄放器êx的值为5x+7,在那个地方需要注意目的操作数必需是一个寄放器。指令效果描述lealS,DD←x>>=n;returnx;}
intmain(){
inta=4,b=3;
intans=shiftlr(a,b);printf(“%d\\n〞,ans);return0;}
shiftlr函数反汇编代码:
0x080483c4:push?p0x080483c5:mov%esp,?p
0x080483c7:shll$0x2,0x8(?p)0x080483cb:mov0xc(?p),ìx0x080483ce:sarl%cl,0x8(?p)0x080483d1:mov0x8(?p),êx0x080483d4:pop?p0x080483d5:ret
从上面的代码我们能够看到,移位量用单个字节编码,由于只同意进行0到31位的移位。位移量能够是一个马上数,或者放在单字节寄放器元素%cl中。指令效果描述imullSR[íx]:R[êx]←S×R[êx]有符号全64位乘法mullSR[íx]:R[êx]←S×R[êx]无符号全64位乘法cltdSR[íx]:R[êx]←符号扩展转换为四字(R[êx])IdivlSR[íx]←R[íx]:R[êx]modS有符号除法R[íx]←R[íx]:R[êx]÷SdivlSR[íx]←R[íx]R[êx]modS无符号除法R[íx]←R[íx]:R[êx]÷S
图4:特别的算术操作
给个例子和其相应的反汇编代码练习一下。#includeintmain(){
inta=6,b=3;
unsignedintc=10,d=2;intans1=a/b;
unsignedintans2=c*d;return0;}
0x08048394:lea0x4(%esp),ìx0x08048398:and$0xfffffff0,%esp0x0804839b:pushl-0x4(ìx)0x0804839e:push?p0x0804839f:mov%esp,?p0x080483a1:pushìx
0x080483a2:sub$0x28,%esp
0x080483a5:movl$0x6,-0x8(?p)0x080483ac:movl$0x3,-0xc(?p)0x080483b3:movl$0xa,-0x10(?p)0x080483ba:movl$0x2,-0x14(?p)0x080483c1:mov-0x8(?p),êx0x080483c4:movêx,-0x2c(?p)0x080483c7:mov-0x2c(?p),íx0x080483ca:movíx,êx0x080483cc:sar$0x1f,íx0x080483cf:idivl-0xc(?p)
0x080483d2:movêx,-0x18(?p)0x080483d5:mov-0x10(?p),êx0x080483d8:imul-0x14(?p),êx0x080483dc:movêx,-0x1c(?p)0x080483df:mov$0x0,êx0x080483e4:add$0x28,%esp0x080483e7:popìx0x080483e8:pop?p
0x080483e9:lea-0x4(ìx),%esp0x080483ec:ret
2、操纵结构
CF:进位标志。最近的操作使最高位产生了进位,它可用来检查无符号操作数的
溢出。
ZF:零标志。最近的操作得出的结果为0。
SF:符号标志。最近的操作得到的结果为负数。
OF:溢出标志。最近的操作导致一个二进制补码溢出——正溢出或负溢出。整型变量a、b和t,用add指令完成等价于C表达式t=a+b的功能。会依照下面的表达式来设置条件码:
CF:(unsignedt)=(short)a;chart4=(char)a!=(char)c;chart5=c>b;
chart6=a>0;
intsum=t1+t2+t3+t4+t5+t6;returnsum;}
intmain(){
intx=5,y=6,z=7;
intans=ctest(x,y,z);printf(“%d\\n〞,ans);return0;}
(gdb)disasctest
0x080483c4:0x080483c5:0x080483c7:0x080483ca:0x080483cd:0x080483d0:0x080483d3:0x080483d6:0x080483d9:0x080483dc:0x080483de:0x080483e1:0x080483e4:0x080483e7:0x080483e9:0x080483ec:0x080483ef:0x080483f2:0x080483f5:0x080483f8:0x080483fa:0x080483fd:0x080483ff:0x08048402:0x08048405:0x08048408:0x0804840b:0x0804840e:0x08048411:0x08048415:0x08048418:0x0804841b:push?pmov%esp,?psub$0x10,%espmov0x8(?p),êxcmp0xc(?p),êxsetl%al
mov%al,-0x1(?p)mov0xc(?p),íxmov0x8(?p),êxcmpêx,íxsetb%al
mov%al,-0x2(?p)mov0x10(?p),êxmovêx,íx
mov0x8(?p),êxcmp%ax,%dxsetge%al
mov%al,-0x3(?p)mov0x8(?p),êxmovêx,íx
mov0x10(?p),êxcmp%al,%dlsetne%al
mov%al,-0x4(?p)mov0x10(?p),êxcmp0xc(?p),êxsetg%al
mov%al,-0x5(?p)cmpl$0x0,0x8(?p)setg%al
mov%al,-0x6(?p)movsbl-0x1(?p),íx
0x0804841f:0x08048423:0x08048425:0x08048429:0x0804842b:0x0804842f:0x08048431:0x08048435:0x08048437:0x0804843b:0x0804843e:0x08048441:0x08048444:0x08048445:指令同义名jmpLabeljmp*OperandjeLabeljzjneLabeljnzjsLabeljnsLabeljgLabeljnlejgeLabeljnljlLabeljngejleLabeljngjaLabeljnbejaeLabeljnbjbLabeljnaejbeLabeljnamovsbl-0x2(?p),êx
addêx,íx
movsbl-0x3(?p),êxaddêx,íx
movsbl-0x4(?p),êxaddêx,íx
movsbl-0x5(?p),êxaddêx,íx
movsbl-0x6(?p),êxlea(íx,êx,1),êxmovêx,-0xc(?p)mov-0xc(?p),êxleaveret跳转条件描述1直截了当跳转1间接跳转ZF相等/零~ZF不相等/非零SF负数~SF非负数~(SF^OF)intabsdiff(intx,inty){
if(x:0x080485a5:0x080485a7:0x080485aa:0x080485ad:0x080485b0:0x080485b2:0x080485b5:0x080485b8:0x080485ba:0x080485bc:0x080485bf:0x080485c1:0x080485c4:0x080485c7:0x080485c9:0x080485cb:0x080485ce:0x080485d1:push?pmov%esp,?psub$0x4,%esp
mov0x8(?p),êxcmp0xc(?p),êx
jge0x80485c1mov0x8(?p),íxmov0xc(?p),êxmovêx,ìxsubíx,ìx
movìx,-0x4(?p)
jmp0x80485cemov0xc(?p),íxmov0x8(?p),êxmovêx,ìxsubíx,ìx
movìx,-0x4(?p)mov-0x4(?p),êxleave
0x080485d2:retcmp0xc(?p),êx
jge0x80485c1mov0x8(?p),íxmov-0x4(?p),êx
从上面的三句我们能够看出那个地方确实是执行if条件语句了。也能够看出if条件语句反汇编后的一些特征,我们一般能够认为cmp+条件跳转指令+jmp跳转,确实是if条件语句反汇编的代码。这关于我们在实际中分析代码需要快速识别一些特征反汇编代码很有关心。也便利我们关于代码的整体结构有更好的认识,记住一些常用的特征代码结构是必要的,这些也能够从正面入手,再反面进行分析,从而能够提高快速分析汇编代码的能力。mov0x8(?p),íx取得xmov0xc(?p),êx取得y
movêx,ìx把y放入寄放器ìx中subíx,ìx得到x–ymovìx,-0x4(?p)
mov-0x4(?p),êx将结果放入êx中返回
由于上面的跳转指令是jge即表示大于等于跳转,而if条件语句本身的比较是用<进行的,因此上面这段汇编代码是先进行else后面的语句体进行执行的。对代码进行分析即能够明白。另外一般函数的返回值基本上用êx寄放器返回的,看最终一句就能够明白了。
C语言提供了好几种循环结构,即while、for和do-while。汇编语言中并没有相应的指令存在,作为替代,将条件测试和跳转组合起来实现循环的效果。比较好玩儿的是,大多数汇编器依照一个循环的do-while形式来产生循环代码。do-while循环
其通用形式是如此的:do
body-statementwhile(test-expr);
循环的效果确实是重复执行body-statement,对test-expr求值,假使求值的结果为非零,就接着循环。注意,body-statement至少执行一次。看看下面举的例子来进行分析。#include#includeusingnamespacestd;intfib_dw(intn){
inti=0;intval=0;intnval=1;do{
intt=val+nval;val=nval;nval=t;
i++;
}while(i:push?p0x080485a5:mov%esp,?p0x080485a7:sub$0x10,%esp
0x080485aa:movl$0x0,-0x4(?p)0x080485b1:movl$0x0,-0x8(?p)0x080485b8:movl$0x1,-0xc(?p)0x080485bf:mov-0xc(?p),íx0x080485c2:mov-0x8(?p),êx0x080485c5:addíx,êx
0x080485c7:movêx,-0x10(?p)0x080485ca:mov-0xc(?p),êx0x080485cd:movêx,-0x8(?p)0x080485d0:mov-0x10(?p),êx0x080485d3:movêx,-0xc(?p)0x080485d6:addl$0x1,-0x4(?p)0x080485da:mov-0x4(?p),êx0x080485dd:cmp0x8(?p),êx
0x080485e0:jl0x80485bf0x080485e2:mov-0x8(?p),êx0x080485e5:leave0x080485e6:ret
这段代码确实是while语句括号进行的条件比较,0x080485da:mov-0x4(?p),êx0x080485dd:cmp0x8(?p),êx
0x080485e0:jl0x80485bf
先将局部变量i的值放入到êx寄放器中,再与传进来的参数n进行比较,假使小于那么进行跳转,我们能够看出while条件语句的反汇编后的特征结构为cmp+条件跳转语句。这也一定程度说明白do-while这种循环结构反汇编后的代码比较少,不明白效率是否有一定的提高,对一些优化能够进行实践操作。while循环的通用形式是如此的:while〔test-expr〕
body-statement
它与do-while的不同之处在于对test-expr求值,在第一次执行body-statement之前,循环就可能中止了。#include#includeusingnamespacestd;
intloop_while(inta,intb){
inti=0;
intresult=a;while(i:push?p0x080485a5:mov%esp,?p0x080485a7:sub$0x10,%esp0x080485aa:movl$0x0,-0x4(?p)0x080485b1:mov0x8(?p),êx0x080485b4:movêx,-0x8(?p)
0x080485b7:jmp0x80485cb0x080485b9:mov0x8(?p),êx0x080485bc:addêx,-0x8(?p)0x080485bf:mov0xc(?p),êx0x080485c2:subêx,0x8(?p)0x080485c5:mov0xc(?p),êx0x080485c8:addêx,-0x4(?p)0x080485cb:cmpl$0xff,-0x4(?p)
0x080485d2:jle0x80485b90x080485d4:mov-0x8(?p),êx0x080485d7:leave0x080485d8:ret
上面红色的红色标记确实是while条件语句反汇编后的特征结构,从正向动身,
再从逆向来分析语言的一些机制关于我们更好的理解一些语言机制的实现编译器在背后实现了一些什么,这些大部分能够从反汇编后的代码看出。for循环的通用形式:
for(init-expr;test-expr;update-expr)
body-statement
C语言标准说明,如此一个循环的行为与下面这段使用while循环的代码的行为一样:init-expr
while(test-expr){
body-statementupdate-expr;}
程序首先会对初始化表达式init-expr求值。然后进行循环,它会先对测试条件test-expr求值,假使测试结果为“假〞就会退出,然后执行循环体body-statement,最终对更新表达式update-expr求值。#include#includeusingnamespacestd;intfib_for(intn){inti;
intval=1;intnval=1;
for(i=1;i:push?p0x080485a5:mov%esp,?p0x080485a7:sub$0x10,%esp
0x080485aa:movl$0x1,-0x8(?p)0x080485b1:movl$0x1,-0xc(?p)
0x080485b8:movl$0x1,-0x4(?p)
0x080485bf:jmp0x80485dc0x080485c1:mov-0xc(?p),íx0x080485c4:mov-0x8(?p),êx0x080485c7:addíx,êx
0x080485c9:movêx,-0x10(?p)0x080485cc:mov-0xc(?p),êx0x080485cf:movêx,-0x8(?p)0x080485d2:mov-0x10(?p),êx0x080485d5:movêx,-0xc(?p)0x080485d8:addl$0x1,-0x4(?p)0x080485dc:mov-0x4(?p),êx0x080485df:cmp0x8(?p),êx
0x080485e2:jl0x80485c10x080485e4:mov-0x8(?p),êx0x080485e7:leave
那个地方的反汇编代码结构与上面的while条件语句是一样的,也说明在高级语言的不同形式语句在底层的表现有可能是一样的或是以相像的方式的来实现的。switch语句提供了依照一个整数索引值进行多重分支的能力,相比起用很长的if-else语句,使用跳转表的优点是执行开关语句的时间和开关状况的数量无关。如此不仅提高了C代码的可读性,而且通过使用一种称为跳转表的数据结构使得实现更加高效。跳转表是一个数组,表项i是一个代码段的地址,那个代码段实现的是当开关索引值等于i时程序应当采取的动作。下面给个程序来个感性的认识。
intswitch_eg(intx){
intresult=x;switch(x){
case100:result*=13;break;case102:result+=10;break;case103:result+=11;break;case104:case
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- (2025年)万荣县省直机关公开遴选公务员笔试题及答案解析
- 2026年福建事业单位招聘(职测)笔试真题及答案
- 人教版一年级下册第二单元《20以内的退位减法》模拟测试卷(含答案解析)
- 农业科技园区建设规划方案
- 内江市威远县(2026年)辅警协警笔试笔试真题(附答案)
- 2025年全国“安全生产月”知识竞赛考试及参考答案
- 2025年军队文职人员统一招聘笔试(新闻传播)模拟题及答案
- 2025年收集中级银行从业资格之中级公司信贷模拟题库及答案
- (2025年)丹东市振安区网格员笔试真题及答案解析
- 2026兴业银行天津分行招聘备考题库及答案详解【网校专用】
- 7《我不是最弱小的》课件(内嵌音视频)-2025-2026学年二年级下册语文统编版
- 2025年宜昌五峰土家族自治县“招才兴业”事业单位人才引进41人笔试历年典型考题(历年真题考点)解题思路附带答案详解
- (部编版2025新教材)道德与法治一年级下册-第1课《有个新目标》课件
- 表达方式(抒情手法)优秀课件
- GJB9001B-2009《质量管理体系要求》
- 小学语文课程标准与教材研究全书ppt完整版课件最全电子教案正本书教学教程
- 油茶籽购销合同书
- 上市公司的行业分析报告
- 九版传染病学配套教学课件病毒性传染病
- GB∕T 40802-2021 通用铸造碳钢和低合金钢铸件
- 化学毒物介绍
评论
0/150
提交评论