前言:学习X86指令体系中的控制转移指令
无条件转移指令
指令格式:JMP LABLE
LABLE是将要转移到的目标地址,那LABLE是否与当前指令在一个代码段,无条件转移可分为段内转移(16位地址)和段间转移(20位地址);而按LABLE的不同寻址方式又可以分为直接寻址和间接寻址。
直接寻址:转移地址在指令代码中
间接地址:转移地址在寄存器或内存单元
段内转移
在当前代码段范围64KB内转移(±32KB范围)成为近转移(NEAR PTR)。转移范围在段内-128至+127范围内称为短转移(SHORT)。段内转移CS段地址不变,只要改变IP的偏移地址
1 | JMP SHORT LABLE ;短转移,直接寻址,目标地址为LABLE |
段间转移
远转移(FAR PTR)从当前代码段转移到另一个代码段(设为代码段2),转移范围为1MB。需要改变CS段地址和IP段地址。因此目标地址必须用一个32位数表达
1 | JMP FAR PTR LABLE ;远转移到代码段2的LABLE,IP ← [LABLE],CS ← [代码段2的段地址] |
条件转移语句JCC
条件转移语句都是段内短转移
条件转移指令的一般格式:JCC LABLE(没这个指令,表示形式)
指令功能:如满足条件,则发生转移:IP ← IP + 8位偏移量;若条件不满足,则不转移,顺序执行下一条指令。转移范围与JMP SHORT指令相同
指令中的条件即为状态标志的状态,条件转移指令可以分为三类:判断单个标志位状态、比较无符号数高低、比较有符号数大小
判断单个标志位状态
- JZ/JE和JNZ/JNE:利用零标志位ZF,判断结果是否为零(或相等)
- JS和JNS:利用符号标志位SF,判断结果是正是负
- JO和JNO:利用溢出标志位OF,判断结果是否产生溢出
- JP/JPE和JNP/JPO:利用奇偶标志位PF,判断结果中”1”的个数是偶还是奇
- JC/JB/JNAE和JNC/JNB/JAE:利用进位标志CF,判断结果是否进位或错位
指令中的Z、S、O、C、P分别表示标志寄存器中的ZF 、SF、OF、CF、PF标志位,指令中的N表示不等(Not),E表示相等(Equal)
比较无符号数高低(条件为一个标志或标志组合)
比较无符号数用高低表示。指令中A表示高(Above),B表示低(Below),利用CF确定高低,利用ZF确定相等
比较有符号数大小(条件为标志组合)
判断有符号数的大小需要组合OF、SF标志,并利用ZF标志确定相等。指令的G表示大(Great),L表示小(Less)
测试CX的值为0,则转移的指令
指令格式:JCXZ LABLE
指令功能:若CX的寄存器的内容为零,则转移到指定地址标号处
循环控制指令
循环指令默认利用CX计数器,属于段内短转移。
指令格式:
LOOP LABLE
- 执行前CX先减1,如果不为0,则转到LABLE执行,否则顺序执行
LOOPZ/LOOPE LABLE
- 执行前CX先减1,如果不为0且ZF = 1,则转到LABLE执行,否则顺序执行
LOOPNZ/LOOPNE LABLE
- 执行前CX先减1,如果不为0且ZF = 0,则转到LABLE执行,否则顺序执行
子程序条用及返回指令
子程序调用指令CALL
CALL指令位于主程序,CALL调用的子程序与CALL指令可以处于同一代码段内,也可以在不同的代码段,因而分段内调用和段间调用。段内直接调用、段内间接调用、段间直接调用、段间间接调用
指令中”NEAR PTR“表示段内调用,”FAR PTR“表示段间调用。汇编程序自动识别”段内”,故可以省略
返回指令RET为子程序最后执行的指令,作用为断点出栈,将堆栈中存放的CALL指令的下一条指令的段地址、偏移地址送给CS、IP(低位CS、高位IP)
RET指令根据段内和段间、有无参数,分成四种类型,需要弹出CALL指令压入堆栈的返回地址
指令格式:
- RET ;无参数段内返回
- RET n ;有参数段内返回
- RET ;无参数段间返回
- RET n ;有参数段间返回
段内返回的功能:偏移地址IP出栈,IP ← SS:[SP],SP ← SP + 2
段间返回的功能:偏移地址IP和段地址CS出栈,IP ← SS:[SP],SP ← SP + 2,CS ← SS:[SP],SP ← SP + 2
RET n为有参数返回,n为1个16位立即数,则堆栈指针SP将增加,即SP ← SP + n。主要用于程序可以方便地从堆栈中去除若干个执行CALL指令以前的入栈的参数