arm

  • 使用专门的跳转指令:B BL BX
    • B offset 跳转
    • BL offset 跳转前将下一条指令地址保存在 LR(link reg / R30)通过 MOV PC,LR 返回
    • BX reg 跳转到寄存器中的地址,如果最低位为 1 则进入 Thumb 状态
    • BLX label 保存,转换状态后跳转
    • BLX reg 通过寄存器判断是否转换状态,保存后跳转
  • 向 PC 寄存器直接写入值,RET 是 MOV PC,LR 的语法糖

x86

  • jmp short 8 位偏移
  • jmp near 16 位偏移
  • jmp far ptr 段地址 + 偏移地址
  • jmp 寄存器
  • jmp (d)word ptr 内存地址
  • call near ptr = push ip ; jmp near ptr 标号
  • call far ptr = push cs; push ip; jmp far ptr 标号
  • call reg = push ip; jmp reg(16)
  • call (d)word ptr mem = (push cs); push ip, jmp (d)word ptr mem
  • ret = pop ip
  • retf = pop ip; pop cs
  • loop label 检测 cx 不为零的时候跳转并递减 cx
  • jcxz label 当 cx 为 0 的时候跳转到标号

JMP 和 CALL 指令能够利用下面的方法来引用另外一个代码段:

  • 目标操作数含有目标代码段的段选择符
  • 目标操作数指向一个调用门描述符,而改描述符中含有目标代码段的选择符
  • 目标操作数指向一个 TSS,而该 TSS 中含有目标代码段的选择符
  • 目标操作数指向一个任务门,该任务门指向一个 TSS,而该 TSS 中含有目标代码段的选择符

当不通过调用门转移控制权到另一个代码段的时候,会检查特权级和类型信息

分三个部分:第一个是 CS 寄存器中现在的 Current Privilege Level,一个是调用的 Request Privilege Level,一个是段表中的 Discript Privilege Level(目的)。DPL 中的 C 状态表示是否为 一致代码段,不是的话必须现在 (C) 等级要等于目的 (D) 才行,请求 (R) 要小于或等于现在(好像没什么用?),加载之后特权等级不变;如果是一致代码段,现在 C 可以大于等于目的 D,忽略对请求 R 的检查,加载之后特权 C 不变(所以可能会出现 CPL 大于 DPL 的情况)

NOTE

注意这里越小权限越高