编程语言
首页 > 编程语言> > 汇编基础之三 -- 汇编指令

汇编基础之三 -- 汇编指令

作者:互联网

指令

详细的指令介绍:https://blog.csdn.net/bjbz_cxy/article/details/79467688

常用的汇编指令有:

指令 宽度    指定内存地址     指定值
MOV DWORD PTR DS:[地址编号], 值             // 值写入内存
MOV DWORD PTR DS:[0x1840FF93], EAX         // eax寄存器中的值写入内存
MOV EAX DWORD PTR DS:[0x0012FF45]          // 内存值写入EAX寄存器

  内存地址可以有以下 的几种书写方式

 PTR DS:[0x10ff93dd]               // 直接指定地址
  PTR DS:[reg]                      // reg为8个寄存器的名称, reg中储存的是一个内存地址
  PTR DS:[reg + 立即数]             // reg值 + 一个数字得到内存地址,实现地址偏移
  PTR DS:[reg + reg*{1,2,4,8}]     // 数组地址的快速寻址
  PTR DS:[reg + reg*{1,2,4,8} + 立即数]  // 利用地址的偏移,这是内存可以快速寻址原因
将ESI储存的内存地址的值,复制到EDI寄存器中保存的内存地址上去。并且ESI和EDI的值会自动加1,也就是内存地址向后移动了一位。
MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]
  
ESI和EDI是可以省略的,默认都是从这两个寄存器中存放的内存地址拷贝,更具每次拷贝的数据宽度,有MOVSB, MOVSW, MOVSD三个快捷的指令,表示移动一个字节,两个字节和四个字节数据宽度。

JCC指令组

上面使用CPM和TEST进行两值得比较,并通过标志位得结果,得到比较得结果,而JCC指令组也是同样得原理。

J是指jump。CC是条件,该条件与EFL标志寄存器中的标志位息息相关。通过获取EFL标志位的值,判断是否满足条件而是否执行JUMP操作。对应了高级语言中的比较运算。

JCC指令中文含义检查符号位典型C应用
JZ/JE 若为0则跳转;若相等则跳转 ZF=1 if (i == j);if (i == 0);
JNZ/JNE 若不为0则跳转;若不相等则跳转 ZF=0 if (i != j);if (i != 0);
JS 若为负则跳转 SF=1 if (i < 0);
JNS 若为正则跳转 SF=0 if (i > 0);
JP/JPE 若1出现次数为偶数则跳转 PF=1 (null)
JNP/JPO 若1出现次数为奇数则跳转 PF=0 (null)
JO 若溢出则跳转 OF=1 (null)
JNO 若无溢出则跳转 OF=0 (null)
JC/JB/JNAE 若进位则跳转;若低于则跳转;若不高于等于则跳转 CF=1 if (i < j);
JNC/JNB/JAE 若无进位则跳转;若不低于则跳转;若高于等于则跳转; CF=0 if (i >= j);
JBE/JNA 若低于等于则跳转;若不高于则跳转 ZF=1或CF=1 if (i <= j);
JNBE/JA 若不低于等于则跳转;若高于则跳转 ZF=0或CF=0 if (i > j);
JL/JNGE 若小于则跳转;若不大于等于则跳转 SF != OF if (si < sj);
JNL/JGE 若不小于则跳转;若大于等于则跳转; SF = OF if (si >= sj);
JLE/JNG 若小于等于则跳转;若不大于则跳转 ZF != OF 或 ZF=1 if (si <= sj);
JNLE/JG 若不小于等于则跳转;若大于则跳转 SF=0F 且 ZF=0 if(si>sj)ag

堆栈指令

ESP:栈顶指针寄存器,记录当前使用的地址,栈的内存空间是存大地址开始使用的 EBP:栈底指针寄存器,记录栈开始的位置。

我们可以使用MOV指令,将数据MOV到ESP寄存器指定的位置,然后使用SUB或者ADD指令,将ESP寄存器的值偏移对应的数据宽度值,实现数据的入栈和出栈操作。基于这样的原理,汇编中提供了PUSH和POP命令

MOV BYTE PTR DS:[ESP], 0xFF          // 向栈中写入一个字节
SUB ESP, 1                           // 栈顶指针偏移一字节

以上两个操作等同于一个push操作
PUSH 0xFF                           // 将0xFF写入到ESP保存的地址处,同时ESP偏移一个数据宽度
PUSH EAX                // EAX中的值入栈
PUSH DWORD PTR DS:[地址]             // 该地址处的值入栈

出栈同理 
POP DWORD EAX                     // 将栈顶的元素取出放入EAX寄存器中保存,同时ESP偏移一个DWORD数据宽度

跳转指令

使用这两个指令需要理解EIP寄存器的作用。当一个程序被编译完成之后,程序的执行方法即已经确定,即A=>B=>C的顺序进行执行,且他们使用的内存空间说连续的,计算机执行一行指令后,下一次要执行的内容都保存在EIP寄存器保存的地址处。所以EIP寄存器指向的内容,就是程序下一次执行的指令。也就是说,A执行时,EIP寄存器中保存的是B的地址,这样执行A后将会获取B的信息并执行。如果A时一个JMP或者CALL指令,执行依次JMP EIP D,这条指令表示将EIP中的值改为D的地址,所以下一次执行的即为D指令。由此实现了跳转。这样的方式当程序跳转到D指令后,程序无法返回B指令了,因为我们找不到B的地址,想要重新回到B指令,需要将B的地址保存,使用时取回即可,通常是将其入栈。这样就和CALL指令的使用方式相同了。

JMP EIP, 地址   // 修改EIP寄存器中的值。
CALL 地址    // 跳转到指定地址,执行该地址的指令,跳转前,将下一行地址入栈,

CALL指令的详细使用在下一章函数中讲解,同时会涉及到堆栈提升与堆栈平衡。

JCC指令中文含义英文原意检查符号位典型C应用
JZ/JE 若为0则跳转;若相等则跳转 jump if zero;jump if equal ZF=1 if (i == j);if (i == 0);
JNZ/JNE 若不为0则跳转;若不相等则跳转 jump if not zero;jump if not equal ZF=0 if (i != j);if (i != 0);
JS 若为负则跳转 jump if sign SF=1 if (i < 0);
JNS 若为正则跳转 jump if not sign SF=0 if (i > 0);
JP/JPE 若1出现次数为偶数则跳转 jump if Parity (Even) PF=1 (null)
JNP/JPO 若1出现次数为奇数则跳转 jump if not parity (odd) PF=0 (null)
JO 若溢出则跳转 jump if overflow OF=1 (null)
JNO 若无溢出则跳转 jump if not overflow OF=0 (null)
JC/JB/JNAE 若进位则跳转;若低于则跳转;若不高于等于则跳转 jump if carry;jump if below;jump if not above equal CF=1 if (i < j);
JNC/JNB/JAE 若无进位则跳转;若不低于则跳转;若高于等于则跳转; jump if not carry;jump if not below;jump if above equal CF=0 if (i >= j);
JBE/JNA 若低于等于则跳转;若不高于则跳转 jump if below equal;jump if not above ZF=1或CF=1 if (i <= j);
JNBE/JA 若不低于等于则跳转;若高于则跳转 jump if not below equal;jump if above ZF=0或CF=0 if (i > j);
JL/JNGE 若小于则跳转;若不大于等于则跳转 jump if less;jump if not greater equal SF != OF if (si < sj);
JNL/JGE 若不小于则跳转;若大于等于则跳转; jump if not less;jump if greater equal SF = OF if (si >= sj);
JLE/JNG 若小于等于则跳转;若不大于则跳转 jump if less equal;jump if not greater ZF != OF 或 ZF=1 if (si <= sj);
JNLE/JG 若不小于等于则跳转;若大于则跳转 jump if not less equal;jump if greater SF=0F 且 ZF=0 if(si>sj)ag

标签:汇编,--,之三,跳转,jump,地址,指令,寄存器,ZF
来源: https://www.cnblogs.com/k5210202/p/13365499.html