博舍

汇编基础最后一篇 机器人编号替换最后一个

汇编基础最后一篇

这是汇编语言基础最后一篇,以后还会更新更高级的汇编知识,并且这部分知识会应用到

逆向编程的环节,这一章介绍汇编基础--机器指令。

一个16比特位的汇编指令:

opcode操作码占用3个比特位,可以表示2的3次方为8种操作

寄存器占用2个比特位,可表示2的2次方为4种可用寄存器

地址空间为2的11次方为2048个可能的内存单元地址可用。

 

inc指令和dec指令

 

 

从图中可以看出这些指令长度仅为一字节,因为每个指令地址相差为1字节。

inceax这条指令的机器码为40, 40为16进制表示,转为二进制为01000000

incecx这条指令机器码为41,41位16进制表示,转换为二进制为01000001

依次展开会发现机器码的规律,开头都为01000XXX

而XXX实际就是寄存器在机器中表示的二进制机器码。

下面是各个寄存器的机器码:

 

下面看下dec寄存器指令图:

 

 

 

dec寄存器指令的格式可以总结为

01001xxx,xxx为寄存器二进制指令格式。

 

 mov 指令

moveax,reg指令图

 

每个指令长度为2字节,从地址偏移可以看出。

将上面指令机器码转为二进制

 

movecx,eax 十六进制为8BC8,二进制表示第二个字节11001000

movecx,ecx 十六进制为8BC9,二进制表示第二个字节为11001001

通过对比二进制,发现第一个字节都为8B,第二个字节分别为C0,C1,C2,C3...C9

movreg,reg指令格式为

10001011 11XXXYYY

XXX为目的寄存器,YYY为源寄存器

 

movreg,imm即将一个立即数移动到寄存器中指令的机器码会是什么样呢?

下图为将立即数移动到寄存器的图示:

 

moveax,1指令机器码为B800000001

movecx,10指令机器码为B90000000A 

两条指令地址相差5个字节,每个字节8bit,可计算出每条指令为40bit长度。

即10个十六进制数表示。而 B800000001和 B90000000A恰巧为10个16进制数字组成。

机器码B800000001 从左向右数,去掉B8占用的一个字节,剩下的四个字节可以看出用来表示

立即数1。同样的道理,可以看出 B90000000A也是这个原理。

如果移动的为负数,怎么表示呢?

 

movedx,-1这个指令我们分析一下-1在机器中的表现形式

负数在机器中以补码的形式表现,-1的补码计算规则为:

1的源码为00000000000000000000 000000000001

按位取反为11111111111111111111111111111110

末尾+1位11111111111111111111111111111111

转换为十六进制为FFFFFFFF恰好就是机器码的最后三个字节表示。

同样的道理适用于movebx,-10

下面分析前两个字节BA,BB,B8,B9分别有什么关联。

 

 

 

 

同步对比可以看出前几个比特位是一样的,都为10111 

后三个比特位分别为000, 001,010,011,这四个二进制码恰好为

几个寄存器的二进制表示方法。所以

movreg,imm机器指令为

10111XXX YYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYY

 

movreg,mem将内存数据移动到寄存器中的机器指令怎么表示?

movmem,reg 将寄存器中的数据移动到内存中,机器指令如何表示?

 

下图定义了变量num1,num2,num3

num1地址为00000000

num2地址为00000004

num3地址为00000008

下图为指令对应的机器码:

除去A1,A3开始的一个字节,剩下的4个字节分别为十六进制4和十六进制8,分别为num2的地址

和num3的地址。

下面分析第一个字节A1和A3规律:

可以得出结论,无论将内存数据移动到eax中,还是将eax中的数据移动到内存中,

最后的4个字节表示的都是内存的地址,第一个字节表示的不同,用来表示两种移动方式的区别。

总结规律如下:

 

moveax,mem10100001YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY

movmem ,eax10100011YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY

 

 下面图表表示了ebx,ecx,edx三种寄存器和内存数据移动指令

可以看出其他寄存器(eax,ecx,edx)和内存之间移动数据的操作指令大小为6字节,多出的为第二字节,

0D,15,1D。

第一字节8B表示从内存移动数据到寄存器,89表示从寄存器移动到内存,如下图所示:

 

第二个字节图表如下:

 

 

通过二进制可以看出前两位都为00,中间三位为001,010,011分别表示ecx,edx,ebx

最后三位为101,其实这个字节不仅仅用于表示移动,还可以表示很多操作,因为ecx为循环控制,

ebx为基址寄存器,edx可用于存余数等等,所以前两位为00,且最后三位为101,这个组合表示移动

操作。中间三位表示操作的寄存器是什么。

该字节概括为如下图所示:

mod字段为00,且r/m字段值为101,它表示地址模式数据置换,也就是指向内存地址模式。

 

add指令sub指令

 add指令很简单,给出图表读者自己分析。

字节转为二进制可以看出从右往左数第3到1位为第二个操作的寄存器,

从右往左数第6到4位表示第一个操作的寄存器,两个寄存器操作模式为第7~16位所表示。

 

movoffset指令 lea指令

 

num2的值为5,地址为00000004,分别将num2的内容移动到esi和edi,再通过lea指令将num2地址

放入esi和edi

 

通过对比可以看出后四个字节都为00000004,但是前两个字节是不一样的。将前两个字节展开

为二进制

由于movesi,num2是将num2数据存入esi,而leaesi,num2是将num2地址放入esi,所以

第一个字节的倒数第二位不同,第一个字节分别为10001011 ,10001101,mov和lea第二个字节是相同的。

下面对比两个lea指令前两个字节 ,第一个字节是相同的,第二个字节为00110101 和00111101

第二个字节中间三位不同,分别为110(esi),111(edi)表示寄存器。

所以可以总结一下,mov指令和lea指令区别在于第一个字节,计算机用第一个字节区别mov和lea指令。

计算机用第二个字节中间三位区别lea指令操作的不同寄存器。

第二个字节和我们上面说过的:

 

 

mod字段为00,且r/m字段值为101,它表示地址模式数据置换,也就是指向内存地址模式。

 

下面看一下movesi,offsetmem和movedi,offsetmem两条指令。

 

 

可以看出movoffset指令为5个字节,比mov和lea指令少了一个字节,因为movoffset仅仅在编译的时候加载地址,

所以不需要lea的第二个字节表示数据移动操作。movoffset是静态的。

movoffset指令esi和edi区别仅仅在第一个字节,展开后可以看到:

 

第一个字节的后三位分别为110(esi),111(edi)。

可以得出结论movoffset的指令第一个字节后三位区别esi还是edi,其余不变。

 

jmp指令

看一则jmp指令操作

 

 

jmp指令机器码为EB+相对偏移地址,

如jmp around为EB04,通知计算机跳转到当前指令指针位置+4字节的位置,

需要普及一个知识,当程序运行的时候,指令指针或者CPU中的指令指针指向下一条将要取到CPU中

被后续执行的指令。当运行到jumparound时,指令指针实际指向了地址000000D8,指令above:nop的位置,

EB04指向为000000DB加上4个字节地址即为000000DC,恰好是around:nop指令地址。

符合逻辑。

下面看下jumpabove指令会跳转到哪里。

EBFC指令FC为11111100,该数值为某个负数的补码,负数补码的计算规则为

符号位不变,其他位按位取反末位+1。

同样的道理,负数补码转为原码,符号位不变,按位取反末位+1

11111100符号位不变,按位取反10000011,末位+1,

变为10000100表示-4.

jmpabove机器指令EBFC跳转到指令指针地址向前移动四个字节的位置。

jmpabove指令运行时,指令指针指向下一条将要取出的指令位置,即000000DC,

000000DC-4为00000008,即above:nop的位置。

 

到此为止机器指令的知识介绍完毕,以后会介绍高级汇编和反汇编的知识,

汇编基础介绍告一段落。

 

我的微信公众号,谢谢关注。

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。

上一篇

下一篇