myunco 发表于 2021-4-26 19:22:16

JMP指令是怎么区分是向上跳转还是向下跳转的?

请花两分钟看完内容再回帖,谢谢了!
我看到说16位位移的范围是 -32768~32767,为此定义了一个标签在jmp下面,在jmp和标签之间定义了个63356个字节的0,编译连接后发现能正确执行。
编译后机器码如下:

https://ae01.alicdn.com/kf/Ue6a6584c3216415c9d048ecc50137682c.jpg
F77C转成十进制后正好是63356
然后我就纳闷了,这不已经超出32767了么,不是应该解释为负数吗,为什么能正确的JMP到偏移为F782的位置?
于是乎我又改了改代码,定义了一个标签在jmp上面,同样在jmp和标签之间定义了个63356个字节的0,但这次编译后的机器码我看不懂了,因为编译后机器码为:
https://ae01.alicdn.com/kf/U7595d89e98bf42d18e7c50a83890508co.jpg
0881转成十进制是2177
我搞不懂2177和63356有什么关系,但是却能正确的跳到标签定义的位置:0003
但如果E98108表示向上跳那么多字节的话,那么向下跳过2177字节的0会怎么表示?
于是我又写了代码测试向下跳2177字节个0,结果却是机器码完全一样。。但却仍然能正确区分向上还是向下。
下面是代码和截图:

T1代码:assume cs:codesg
codesg segment
    mov ax,1
    s1:db 63356 dup(0)
    start:jmp near ptr s1
    mov cx,ax
codesg ends
end startT2代码:assume cs:codesg
codesg segment
    mov ax,1
    start:jmp near ptr s2
    db 2177 dup(0)
    s2:mov cx,ax
codesg ends
end start对比截图:
https://ae01.alicdn.com/kf/U5305b17c732942de8bf8bbd44ecf147af.jpg可以看到,两个不同方向的jmp指令的机器码居然完全一样,但是debug解析出来的汇编指令却仍然能正确的区分出向上跳转还是向下跳转
这是什么原理?不是说16位位移的范围是 -32768~32767 吗?为什么能正确向上跳过63356个字节的0?为什么相同的机器码又能正确的向下跳过2177个字节的0?

人造人 发表于 2021-4-26 20:42:20

jmp near ptr 标号,它实现的是段内近转移。
其功能是:(ip)=(ip)+16位位移

0xf77f + 0x03 + 0x0881 = 0x10003
ip寄存器是16位的,只能保存低16位,前面的1丢弃,所以ip寄存器的内容是0x0003


人造人 发表于 2021-4-26 20:44:23

0x03 + 0x03 + 0xf77c = 0xf782

人造人 发表于 2021-4-26 20:47:02

cpu可不关心你往哪里跳,它只是做加法,把结果给ip寄存器
ip是16位的寄存器,超过16位的部分被丢弃
页: [1]
查看完整版本: JMP指令是怎么区分是向上跳转还是向下跳转的?