Linux下的汇编与Windows汇编最大的不同就是第一个操作数

2020-02-21 23:13

Linux下的汇编与Windows汇编最大的不同就是第一个操作数 1、 差不多操作指令

简单的操作数类型说明,一般有三种,

〔1〕马上数操作数,也确实是常数值。马上数的书写方式是“$”后面跟一个整数,比如$0x1F,那个会在后面的具体分析中见到许多。 〔2〕寄存器操作数,它表示某个寄存器的内容,用符号Ea来表示任意寄存器a,用引用R[Ea]来表示它的值,这是将寄存器集合看成一个数组R,用寄存器表示符作为索引。

b字节值的引用。通常能够省略下标b。

图1表示有多种不同的寻址模式,一个马上数偏移Imm,一个基址寄存器Eb,一个变址或索引寄存器Ei和一个伸缩因子s。有效地址被计算为Imm+R[Eb]+R[Ei]*s,关于这中寻址方式,我们能够在数组或者结构体中进行对元素进行访问时会用到。 操作数类型 格式 操作数值 名称 马上数 $Imm Imm 马上数寻址 寄存器 Ea R[Ea] 寄存器寻址 寄存器 Imm M[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,D D←S 传送双字 movlS,D D←S 传送字 movlS,D D←S 传送字节 movlS,D D←符号扩展〔S〕 传送符号扩展的字 节 movlS,D D←零扩展〔S〕 传送零扩展的字节 pushlS R[%esp]←R[%esp]–压栈 4; M[R[%esp]]←S poplD D←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.c studyrush@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?p 0x080483c5: mov%esp,?p 0x080483c7: sub$0x10,%esp 0x080483ca: mov0x8(?p),êx 0x080483cd: mov(êx),êx 0x080483cf: movêx,-0x4(?p) 0x080483d2: mov0x8(?p),íx 0x080483d5: mov0xc(?p),êx 0x080483d8: movêx,(íx) 0x080483da: mov-0x4(?p),êx 0x080483dd: leave 0x080483de: ret Endofassemblerdump.

进一步来分析上面的反汇编代码,那个地方的代码可能与前面的讲的指令操作有一些不同,因为这是很正常的,不同的操作系统应该有所差别,这也是汇编语言一般与平台有关,移植性并不好。 push?p mov%esp,?p sub$0x10,%esp

对有过反汇编的人对上面的代码确信可不能陌生,那个地方确实是将ebp进栈,保存esp的值,并为局部变量预留空间。要记得源操作数与目的操作数的位置,前面有讲的。那个地方也一定程度对C语言中的指针使用进行了说明。看源代码能够明白。

mov0x8(?p),êx mov(ê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),íx mov0xc(?p),êx movêx,(íx)

那个地方与上面的分析类似,并没有出现局部变量,能够说明那个地方是函数参数在进行交换。那个地方的操作数方式是寄存器——存储器

mov-0x4(?p),êx通过寄存器eax将值返回,记住一般函数的返回值基本上

通过eax寄存器返回的。 0x080483dd: leave 0x080483de: ret函数返回

分析完反汇编代码之后有没有看出来函数调用是采纳哪种调用约定呢?事实上确实是C调用方式〔__cdecl〕的方式。 //程序exchange.c,表示交换两个数。 #include #include

intexchange(int*xp,inty) {

intx=*xp; *xp=y;

return(x); }

intmain() {

inta=4;

intb=exchange(&a,3);

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,D D←&S 加载有效地址 inclD D←D+1 加1 declD D←D-1 减1 neglD D←-D 取负 notlD D←~D 取补 addlS,D D←D+S 加法 sublS,D D←D-S 减法 iImullS,D D←D*S 乘法 xorlS,D D←D^S 异或 orlS,D D←D|S 或 andS,D D←D&S 与 sallk,D shllk,D sarlk,D shrlk,D D←D<>k 算术右移〔符号位扩展〕 D←D>>k 逻辑右移〔0扩展〕 图3:整数算术操作 注:后缀l表示对双字进行操作,还能够为w和b分别表示字和字节。 练习一下下面的移位操作指令 #include intshiftlr(intx,intn) {

x<<=2; x>>=n; returnx; }

intmain() {

inta=4,b=3;

intans=shiftlr(a,b); printf(“%d\\n”,ans); return0; }

shiftlr函数反汇编代码:

0x080483c4: push?p 0x080483c5: mov%esp,?p

0x080483c7: shll$0x2,0x8(?p) 0x080483cb: mov0xc(?p),ìx 0x080483ce: sarl%cl,0x8(?p) 0x080483d1:mov0x8(?p),êx 0x080483d4:pop?p 0x080483d5:ret

从上面的代码我们能够看到,移位量用单个字节编码,因为只同意进行0到31位的移位。位移量能够是一个马上数,或者放在单字节寄存器元素%cl中。 指令 效果 描述 imullS R[íx]:R[êx]←S×R[êx] 有符号全64位乘法 mullS R[íx]:R[êx]←S×R[êx] 无符号全64位乘法 cltdS R[íx]:R[êx]←符号扩展转换为四字 (R[êx]) IdivlS R[íx]←R[íx]:R[êx]modS 有符号除法 R[íx]←R[íx]:R[êx]÷S divlS R[íx]←R[íx]R[êx]modS 无符号除法 R[íx]←R[íx]:R[êx]÷S


Linux下的汇编与Windows汇编最大的不同就是第一个操作数.doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:《物业设备设施管理》形成性考核册参考答案

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: