jmp为无条件转移, 可以只修改IP, 也可以同时修改CS:IP
jmp指令要给出两种信息:
- 转移的目的地址
- 转移的距离( 段间转移, 段内短转移, 段内近转移)
语法格式:
- jmp short 标号 ==> 短转移, 指定修改IP范围-128~127 ( 8位 )
- jmp near ptr 标号 ==> 近转移, 修改ip范围-32769~32767 ( 16位 )
- jmp far ptr 标号 ==> 段间转移, 也叫远转移,
短转移实例
code segment
assume cs:code
start:
mov ax, 0
jmp short s
add ax, 1
s:
inc ax
code ends
end start
上述代码从jmp直接跳到了s, 所以结果ax为1
汇编指令, 可以翻译为机器码, 例如
汇编指令 | 机器指令 |
mov ax, 0123 | B8 23 01 |
mov ax, ds:[0123] | A1 23 01 |
push ds:[0123] | FF 36 23 01 |
汇编指令中, 操作码和数据( 或地址 ), 是分开的, 例如可以看到ax对应B8, 而0123则原封不动
当我们使用 debug 调试jmp短转移程序时, 使用 u 翻译指令, 会同时得到机器码和指令, 但我们发现, jmp 0008 的机器码为 EB03, 即cpu并不知道cs:ip
修改短转移程序, 在add ax, 1后一句增加一个add ax, 1然后再调试时, 发现得到的是jmp 000B对应 EB06, 我们发现了cpu不需要cs:ip就可以实现转移, 而它是根据偏移地址取得的, 一句add ax, 1是3个字节( 机器码050100 ), 那么2句重复就是06, 它的机器码( 操作码EB, 数据06)
jmp短转移中, 简记为 ip = ip + 偏移, 地址的 -128~127是补码形式
如果跳转的标号, 在当前指令前面, 即偏移为负数时, 是否死循环? 为何不使用cs:ip转移? 在实际程序中cs:ip是否会变化而导致跳转失败?
远转移实例
短转移, 近转移语法非常相似, 几乎没有区别, 而远转移却相差甚远
jmp far ptr 标号, 需要使用 cs:ip 指定转移的cs:ip ( 如果少于128, 则会自动变成短转移)
这里, 使用dup开辟一个128单位空间, 确保它跳转的超过128, 否则会自动变为短转移
code segment
assume cs:code
start:
mov ax, 0
jmp far ptr s
db 128 dup(0)
add ax, 1
s:
inc ax
code ends
end start
使用debug得到的指令, jmp 076c:008b, 对应的机器码为 EA8B006C07
在这里, 076c表示 cs, 而 008b则是ip, 可以看到跳转的确实是cs:ip, 而不是偏移地址
jmp的其他用法
jmp还有其他语法, 例如
- jmp 16位寄存器 ( 如: jmp ax, ax中存放了ip )
- jmp 内存地址 ( 重点介绍 )
在内存中使用jmp, 有以下两种语法
- jmp word ptr 内存单元(16位段内转移, 只能是ip)
- jmp dword ptr 内存单元地址( 双字, 32位, 段间转移)
需要注意, 高位cs, 低位ip, 那么内存中实际是, ip, cs ( ip=内存地址, cs=内存地址+2)
以下实例, 将跳转到 0:0123H
mov ax, 0123H
mov ds:[0], ax
mov word ptr ds:[2]
jmp dword ptr ds:[0]