Chinaunix首页 | 论坛 | 博客
  • 博客访问: 180535
  • 博文数量: 29
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 601
  • 用 户 组: 普通用户
  • 注册时间: 2013-07-03 18:51
个人简介

大数据算法,分布式技术,spark技术爱好者

文章分类

全部博文(29)

文章存档

2015年(4)

2014年(3)

2013年(22)

分类: 嵌入式

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到代码段头部,合法结束。

阅读(1409) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~