大数据算法,分布式技术,spark技术爱好者
分类: 嵌入式
2013-07-09 21:18:55
1.标号和地址其实是一种东西。offset 可以把标号转换成偏移地址 。下面一些用地址做参数的操作符也同样可以用标号。比如jmp,call。需要牢记,标号就是偏移地址的助记符。
2.jmp short +标号:用在短距离跳转,编译后实际上保存在命令中的是相对跳转距离-128---+127,有可能有负数的,读机器码的时候要小心。
jmp near ptr +标号:段内近转移,编译后保存的也是相对跳转距离。-35768--+35767
jmp far ptr + 标号:段间转移(看后面分析)。
因为标号就是地址,所以相对应的地址格式(地址必须存在内存中):
jmp word ptr
jmp dword ptr
但是这些和'jmp reg'中reg存的地址一样,都是绝对地址,不是相对地址。
而jmp + 立即数的形式(偏移或者段:偏移)只有在debug下可以使用,因为已经加载到内存,有绝对地址可用。
其实 jmp 标号 包含了所有jmp X 标号的形式。编译器自动识别。
jmp far ptr +其他段的标号。无法编译通过,提示missing or unreachable cs。这是为什么呢?
经过反复试验,发现当汇编代码不同段中同时出现标号时,编译器无法识别哪一个段是代码段。也就是说标号只能出现在同一个段中。也就是说代码段一般只有一个。也就是说段间跳转纯属瞎扯。。。既然段间跳转纯属瞎扯。其实,jmp far ptr本来也没有编译出绝对地址,在程序加载到内存之前,也不知道标号的绝对地址,只是在加载的时候会显示成绝对地址。所以,更科学的理解应该是,jmp near ptr 和jmp far ptr一样,只不过后者用绝对地址,前者用相对地址,并不存在段内段间的分别。
看到网上的解答有这样的:
assume cs:codesg
codesg segment
start:
jmp far ptr [newseg]
newseg dw codesg2
dw 0
codesg ends
codesg2 segment
mov ah, 2
mov dl, 'X'
int 21h
mov ax, 4c00h
int 21h
codesg2 ends
end start
这其实用jmp near ptr完全可以,况且这个代码完全是错的。调试发现根本无法运行。
3.loop和jmp
loop是循环指令,所有的循环指令都是短转移。
loop是要占用cx的,jmp short不用。可以用cx做更灵活的应用。
loop要先做一个cx--的运算。如果想用外来数据修改cx以后,判断cx是否为0,退出循环,必须先做一步cx++运算,就是inc cx。这就是习题中的一个问题:用loop代替jcxz:
s:mov cl,[bx]
mov ch,0
inc cx
inc bx
loop s
dec bx
mov dx,bx
可谓巧妙,但是很难读,也不推荐这么写。
4.总结:
jmp short/near ptr/far ptr/word ptr/dword ptr + ...或者
jmp reg
5.jcxz:比较容易忘记的转移指令。和loop一样是条件转移指令。所以可以互相转换。意识短jmp,编译以后记录相对位移。
6.习题,奇怪的程序:复制一个字节,恰好是jmp命令,并没有复制jmp到的偏移,而nop就是0填充,直接jmp到代码段头部,合法结束。