8086汇编基础一点通

汇编学习

对于一名安全工程师,不会不懂汇编,只能说是一个半吊子的安全工程师。汇编的学习不是为了写汇编,而是为了读懂汇编进而读懂逻辑,进而攻击或者防护。
此贴为原创博客,如转发请注明出处,多谢!!!!

进制

  1. 计算机使用的是二进制,只有0和1,理解什么是进制,进制间的换算。
  2. 二进制转十六进制是必须要掌握的。
  3. 什么是大端格式(数据高位在低位),什么是小端格式(相反)。

进制之间的加减乘除原理都是相同的,只不过生活中我们习惯了十进制,所以思维惯性会不适应二进制或者十六进制的加减乘除。熟练的对十六进制的加减运算是一个很必要的功底。

数据宽度

  1. 位 bit
  2. 字节 byte
  3. 字 word (2 bytes)
  4. 双字 double word (4 bytes)

计算机中只有后三种宽度。64位的汇编指令会不会有8 bytes,我就不知道了。

有符号数,无符号数

这两种需要掌握。

  1. 对于有符号数最高位为1就是负数,为0就是正数。
  2. 无符号数当然没有负数了,所以最高位也是需要换算成数值的。
  3. 有符号数的负数如何表示,需要掌握。

有符号数的编码规则:
原码:最高位为符号位,其余位的绝对值
反码:正数反码和原码相同,符号位1时,其余位对原码取反
补码:正数与原码相同,符号位1时,其余位对反码加1

举例: -1 (byte)
原码: 1000 0001
反码: 1111 1110
补码: 1111 1111

位运算

与运算(and &)
或运算(or |)
异或运算(xor ^)
非运算(not ~)
左移运算(shl <<)
右移运算(shr >>) shr:高位补0 sar:高位补符号位

计算机只会位运算,加减乘除都是通过位运算进行操作的。
举例加法:

  1. 亦或操作得到无进位的结果
  2. 与操作的结果判断是否有进位
  3. 如果有进位,与操作结果左移1位,然后与亦或操作结果做加法,以此类推

汇编学习工具

DTDBUG,自行搜索下载即可。
在这里插入图片描述

通用寄存器

CPU中存取数据的地方。
32位:EAX、EBX、ECX、EDX、ESP、EBP、ESI、EDI
16位:AX BX CX DX SP BP SI DI (低16位)
8位: AL BL CL DL (低8位)
AH BH CH DH (低16位中高8位)
16位和8位仅仅是32位寄存器的低位

内存

每一个进程都有4GB的内存(2的32位),逻辑内存。
内存地址是一个32的地址编号。0x00000000 ~ 0xffffffff
5种寻址的表现形式:

  • 立即数 [0x11111111]
  • 寄存器 [EAX]
  • 寄存器+立即数 [EAX+4]
  • 寄存器+寄存器*{1,2,4,8} [EAX+ECX*2]
  • 寄存器+寄存器*{1,2,4,8} +立即数 [EAX+ECX*2+100]

堆栈

就是一块内存,用来做堆栈,先进后出。
堆栈从高地址往低地址使用,如果用完堆栈,会造成堆栈溢出。

汇编指令

  1. MOV指令
    立即数到寄存器
    寄存器到寄存器(宽度必须一致)
    MOV EAX, EBX
    立即数到内存(宽度必须一致)
    MOVE BYTE(WOED/DWORD) PTR DS:[0x********], 1
    寄存器到内存(宽度必须一致)
    内存到寄存器(宽度必须一致)
    内存到内存(不允许)
  2. ADD指令 加法指令
    ADD EAX, ECX
    内存到内存(不允许)
  3. SUB指令 减法指令
    内存到内存(不允许)
  4. AND指令
    内存到内存(不允许)
  5. OR指令
    内存到内存(不允许)
  6. XOR指令
    内存到内存(不允许)
  7. NOT指令
  8. MOVS指令
    移动数据,内存到内存
    MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI] 简写 MOVSB(/W/D)
    … WORD/DWORD …, WORD/DWORD …
    复制一次内存,ESI,EDI将会自动增加字长
    ELF标志寄存器,当DF标志位为0时,ESI,EDI增长;当DF为1时,ESI,EDI递减
  9. STOS指令
    把EAX/AX/AL的值存储到EDI指定的内存中 简写 STOSB(/W/D)
    复制一次内存,EDI将会自动增加字长
    ELF标志寄存器,当DF标志位为0时,EDI增长;当DF为1时,EDI递减
  10. REP指令
    可重复执行 MOVS 或者 STOS指令,重复的次数为ECX的值
    MOV ECX,10
    REP MOVSD BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]
    一次性拷贝16个字节
  11. PUSH 指令
    PUSH 立即数/寄存器/内存
    将数据压入堆栈,ESP寄存器将会指向栈顶
  12. POP指令
    POP EAX
    与PUSH相反
  13. JMP指令
    无条件跳转到相应地址,并且修改EIP寄存器(指向下一条要执行的指令)
    JMP 立即数/寄存器/内存
    JMP的本质其实就是修改EIP
  14. CALL指令
    CALL指令的作用
    1、将当前指令下一行指令压堆栈栈
    2、修改EIP为下一条要执行的地址
    在这里插入图片描述
  15. RETN指令
    栈顶的值出栈并修改EIP为出栈的值。这就是它实质性的作用。

堆栈平衡

调用函数之后,堆栈应该恢复到调用之前的状态。

  • 函数退出后恢复平衡,外平栈
    PUSH 1
    CALL 0x11111111
    ADD ESP, 4 //为了平衡堆栈
  • 函数退出前恢复平衡,内平栈
    PUSH 1
    CALL 0x11111111

    0X11111111: …

    0X11111118: RETN 4 //恢复堆栈平衡

ESP寻址

ESP寻址有弊端,当调用的函数(CALL指令)嵌套太复杂,很难维护。因为我们知道需要维护函数的栈平衡,所以当更深层的函数调用造成栈的复杂度就会越来越高。
在这里插入图片描述
此图仅仅是演示每当进入一个CALL指令,如果PUSH了很多数据到堆栈,那在堆栈中使用就很困难,而且每当出函数需要保持堆栈平衡。

EBP寻址

EBP是基址寄存器
这里引用他人的一篇帖子,写的很好。(这篇帖子的上半段我感觉说的不太对,从这篇帖子的个人理解开始还是写的很好的)
https://blog.csdn.net/u013152417/article/details/44308289
所以基址选址就方便多了,而且恢复简单,一目了然。

JCC指令

主要是更改EIP指令寄存器。JCC指令的目的就是了解和掌握标记寄存器EFLAGS
在这里插入图片描述
运算相关的指令都会影响标志寄存器。

  • CF:无符号数的计算结果有没有溢出(发生进位或者借位)
  • PF:奇偶校验位,如果最低有效字节统计1的个数为偶数时为1,否则为0。通常用作传输过程中的奇偶校验。
  • ZF:如果运算的结果为0,则为1
  • SF:符号位,判断运算结果是正(0)还是负数(1)
  • OF:有符号数,如果溢出则置位1
  • DF:方向标识位,上面有所描述,MOVS, STOS指令等
    借鉴一下图:用到时查查就可以
    https://blog.csdn.net/fengshh2301/article/details/53327195
    JCC跳转只和Flag相关

判断两个数是否相等:只影响标准寄存器
CMP EAX,EBX (CMP和SUB的操作类似,只不过没有赋值到EAX)
TEST EAX, EAX (TEST 和 AND类似,也是不赋值到EAX中)
发表的第一篇blog,希望多多支持,后续把自己的一些心德也慢慢更新下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诚学X

写作不易,请多鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值