第九章
8086cpu转移指令分为:无条件转移指令(jmp)、条件转移指令、循环指令(loop)、过程、中断。
offset 由编译器处理的指令,取得标号的偏移地址。
jmp指令:
段内短转移:jmp short 标号(转到标号处执行指令)ip修改范围:-128~127
段内近转移:jmp near ptr标号ip修改范围:-32768~32767
段间转移(远转移):jmp far ptr 标号;改变cs和ip
CPU执行jmp时不需要知道转移的目的地址。jmp指令对应的机器码中,包含的是转移的位移。位移是编译器根据汇编指令中的标号计算出的。
汇编编译器对 “jmp X 标号”格式的汇编指令 的相关处理:
1 向前转移:
s
......
jmp s
编译器有一个地址计数器AC,编译器在编译时,每读到一个字节,AC就加1。当编译器遇到伪操作如db时,根据具体情况增加AC。如:s:.....jmp s(涵各种方式,远转移之类),编译器读到s,几下AC值as,读到jmp s后记下AC值aj,编译器根据as-aj计算出位移量disp。此时编译器做如下处理:
(1)如果disp在【-128,127】,不管指令格式是远转移还是什么,都变成jmp short s所对应的机器码(EB DISP),占两个字节。
(2)如果disp在【-32768,32767】,则jmp short s将产生编译错误。编译器将其他类型转为jmp near ptr s(EB DISP),占3个字节。
2 向后转移:
jmp s
.....
s
此时编译器读到jmp指令时,由于还没有读到标号s,所以不能确定标号是的AC值,也就是说无法确定位移量。
此时编译器记下jmp指令的位置和AC值aj,对于jmp short s,编译器生成EB 和一个nop指令(预留一个字节的空间)存放8位disp。
对于jmp s/jmp near ptr s,编译器生成EB,两个nop指令。
对于jmp far ptr s ,编译器生成EB,4个nop指令。
做完以上,编译器继续工作,读到标号s,记下AC值as,计算出位移量disp=as-aj。
jmp reg(16);ip=16位reg中
jmp word ptr 内存单元(段内转移);从内存单元处存放的字是转移的目的的偏移地址。
jmp dword ptr内存单元(段间转移),从内存单元处存放的2个字,高地址是段地址,低地址是偏移地址。、
有条件转移指令都是短转移。
jcxz 标号;如果cx为0,则转到标号处执行,否则向下顺序执行。
所有的循环指令都是短转移。
loop:
cx--;
if(cx!=0)jmp short 标号
根据位移转移:利于程序段在内存中的浮动装配。
第十章:
ret指令,用栈中的数据修改ip,实现近转移。(ip)=(ss*16+sp),sp=sp+2;
retf指令,用栈中数据修改cs,ip,实现远转移。(ip)=(ss*16+sp),sp=sp+2;(cs)=(ss*16+sp),sp=sp+2;
call指令,(不能实现短转移)
call 标号:将当前ip压栈,转到标号处执行。
call far ptr 标号实现段间转移,先将cs压栈,再将ip压栈。
call 16位reg:(push ip,jmp 16位reg)
call word ptr 内存单元地址:
call dword ptr 内存单元地址
///////////////////////////////////////////////////////////////////////////////////////////////////
call和ret联用,call在转去执行子程序之前,call指令后面的指令将存储在栈中,所以程序在后面使用ret指令,用栈中的数据设置cs:ip,从而转到call后面的指令执行。
///////////////////////////////////////////////////////////////////////////////////////////////////
参数和结果传递问题:
用寄存器传,数量不够。
用内存空间传。
用栈传。
由于在子程序中可能改变了寄存器的内容,所以在在子程序开始时将子程序使用的寄存器入栈,保存数据,函数返回时要按顺序出栈,恢复数据。
第十一章:
8086CPU标志寄存器(flag)有16位,存储程状态字(PSW),flag是按位起作用。ZF,PF,SF,OF,CF.