【汇编】 6、流程转移和子程序 | 您所在的位置:网站首页 › 程序的转移和浮动 › 【汇编】 6、流程转移和子程序 |
目录 6.1、“转移”综述 1、转移指令 2、转移指令的分类 6.2、操作符offset 1、作用 2、练习 6.3、jmp指令 1、无条件转移指令 2、依据位移进行转移 3、温馨提示 4、两种段内转移 5、远转移:jmp far ptr 标号 6、转移地址在寄存器中 7、转移地址在内存中 8、JMP指令小结 6.4、其他转移指令 1、JCXZ指令 2、loop指令 编辑 3、根据位移进行相对转移的意义 6.5、call指令和ret指令 1、模块化程序设计 2、call指令 (1)格式:call 标号 (2)指令“call far ptr 标号”实现的时段间转移 (3)转移地址在寄存器中的call指令 (4)转移地址在内存中的call指令 3、返回指令:ret和retf 6.6、call和ret的配合使用 1、具有子程序的源程序框架 2、应用 6.7、mul指令 1、格式 2、应用 示例1 示例2 6.8、汇编语言的模块化程序设计 1、参数和结果传递的问题 (1)用寄存器来存储 6.9、寄存器冲突问题 1、子程序标准框架 2、示例1 1)源码 2)查看源码 3)结果比较 6.10、标志寄存器 1、标志(flag)寄存器的结构 2、标志寄存器的作用作用 3、标志寄存器值得解读 4、直接访问标志寄存器得方法 5、各个标志详解 5.1、ZF-零标志(Zero Flag) 5.2、PF-奇偶标志(Parity Flag) 5.3、SF-符号标志(Sign Flag) 5.4、CF-进位标志(Carry Flag) 5.5、OF-溢出标志(Overflow Flag) 5.6、综合 6.1、“转移”综述 1、转移指令可以控制CPU执行内存中某处代码的指令 可以修改IP、或同时修改CS和IP的指令 2、转移指令的分类 按转移行为按指令对IP的修改范围按转移指令段内转移段间转移段间短转移段间近转移无条件转移指令条件转移指令循环指令过程中断只修改IP同时修改CS和IPIP修改范围JMPJCXZLOOP jmp axjmp 1000:0-128~127-32768~327686.2、操作符offset 1、作用 用操作符offset取得标号的偏移地址 格式为:offset 标号 例如: assume cs:code code segment start: mov ax,offset start ;相当于mov ax,0,标号所在地址为0 s:mov ax,offset s ;相当于mov ax,3,标号所在地址为3 mov ax,4c00h int 21h code ends end start2、练习 问题:有如下程序段,添加2条指令,使得该程序在运行中将s处的第一条指令复制到s0处。 assume cs:code code segment s:mov ax,bx mov si,offset s mov di,offset s0 ______________________________ ______________________________ s0:nop nop code ends end s ;nop即空,机器码占一个字节,起到占位的作用
分析: (1)s、s0处的指令所在的内存单元的地址分别是 cs:offset s和cs:offset s0 (2)将s处的数据复制到s0处,等价于 将cs:offset s处的数据复制到cs:offset s0处 (3)地址如何表示? 段地址在cs中,偏移地址在si、di中 (4)要复制的数据有多长? mov ax,bx指令长度为两个字节,即一个字
补齐代码: assume cs:code code segment s:mov ax,bx mov si,offset s mov di,offset s0 mov ax,cs:[si] mov cs:[di],ax s0:nop nop code ends end s6.3、jmp指令 1、无条件转移指令 (1)功能:无条件转移,可以修改IP,也可以同时修改CS和IP (2)给出的两种信息:转移的目的地址、转移的距离 段间转移(远转移)jmp 2000:1000段内短转移jmp short 标号IP(-128~127)8位转移段内近转移jmp near ptr 标号IP(-32768~32767)16位转移 2、依据位移进行转移JMP short的机器指令中,包含的是跳转到指令的相对位置,而不是转移到目的地址。 assume cs:code code segment start: mov ax,0 jmp short s add ax,1 nop nop s:inc ax code ends end start分析:jmp short s指令的读取和执行 (1)(IP)=0003,CS:IP指向EB 05(jmp的机器码) (2)读取指令码EB 05进入指令缓冲器; (3)(IP)=(IP)+所读取指令的长度 =(IP)+2 =0005,CS:IP指向add ax,0001; (4)CPU执行指令缓冲器中的指令EB05; (5)指令EB05执行后,(IP)=(IP)+05 = 000AH,CS:IP指向inc ax。 3、温馨提示 如果end start命令错写成ends start,debug挂载的时候则会出现:“access denied” 拒绝挂载的错误提示,编译连接的时候不会提示。 4、两种段内转移 (1)短转移:jmp short 标号 功能:IP=IP + 8位位移 8位位移 = 标号处的地址 - JMP指令后的第一个子节的地址 short指明此处的移位是8位位移 8位位移的范围为-128~127,用补码表示 8位位移由编译程序在编译时算出(2)近转移:jmp near ptr 标号 功能:IP = IP + 16位位移 16位位移 = 标号处的地址 - JMP指令后的第一个子节的地址 near ptr指明此处的位移为16位位移,进行的是段内近转移 16位位移的范围为-32769~32767,用补码表示 16位位移由编译程序在编译时算出5、远转移:jmp far ptr 标号 远转移jmp far ptr 标号进转移jmp near ptr 标号段间转移段内转移far ptr指明了跳转到的目的地址,包含了标号的段地址CS和转移地址IPnear ptr指明了相对于当前IP的转移,而不是转移的目的地址 assume cs:code code segment start:mov ax.0 mov bx,0 jmp far ptr s db 256 dup(0) s:add ax,1 inc ax code ends end start assume cs:code code segment start:mov ax,0 mov bx,0 jmp near ptr s db 256 dup(0) s:add ax,1 inc ax code ends end start 6、转移地址在寄存器中指令格式:jmp 16位寄存器 功能:(IP)=(16位寄存器) assume cs:code code segment start: mov ax,0 mov bx,ax jmp bx mov ax,0123h code ends end start 7、转移地址在内存中 jmp word ptr 内存单元地址jmp dword ptr 内存单元地址段内转移段间转移从内存单元地址处开始存放着1个字,是转移的目的偏移地址从内存单元地址处开始存放着2个字,高地址处的字是转移的目的段地址,低地址处是转移的目的偏移地址mov ax.0123h mov ds:[0],ax jmp word ptr ds:[0] 执行后, (IP)=0123h
mov ax,0123h mov [bx],ax jmp word ptr [bx] 执行后, (IP)=0123h mov ax,0123h mov ds:[0],ax mov word ptr ds:[2],0 jmp dword ptr ds:[0] 执行后,(CS)=0; (IP)=0123h CS:IP指向0:0123h
mov ax,0123h mov [bx],ax mov word ptr [bx+2],0 jmp dword ptr [bx] 执行后,(CS)=0; (IP)=0123h CS:IP指向0:0123h 8、JMP指令小结 6.4、其他转移指令 1、JCXZ指令 格式:jcxz 标号 (jmp cx ?= zero) 功能:若(cx)= 0,则转移到标号处执行; 若(cx)≠ 0,则什么也不做,程序向下执行。 (cx)= 0时,(IP)=(IP)+ 8 8位位移 = 标号 处的地址 - JCXZ指令后的第一个字节的地址 8位位移的范围是-128~123,用补码表示 8位位移由编译程序在编译时算出注释:JCXZ是有条件转移指令 (1)所有的有条件转移指令都是短转移 (2)对IP的修改范围都为-128~127 (3)在对应的机器码中包含转移的位移,而不是目的地址 assume cs:codesg codesg segment start: mov ax,2000h mov ds,ax moc bx,0 s:mov cx,[bx] jcxz ok inc bx inc bx jmp short s ok:mov dx,bx mov ax,4c00h int 21h codesg ends end start 2、loop指令![]() 对IP的修改是根据转移目的地址和转移起始地址之间的位移来进行的 jmp short 标号 jmp near ptr 标号 jcxz 标号 loop 标号在它们对应的机器码中不包含转移的目的地址,而是包含的是到目的的地址的位移。 这样的设计,方便程序端在内存中的浮动装配。
6.5、call指令和ret指令 1、模块化程序设计 调用子程序:call 返回:ret 实质:流程转移指令,它们都修改IP,或者同时修改CS和IP mov ax,0 call s mov ax,4c00h innt 21h s:add ax,1 ret 2、call指令 (1)格式:call 标号CPU执行call指令,进行两步操作 (1)将当前的IP或CS和IP压入栈中 (SP)=(SP)-2 ((SS)*16 +(SP))=(IP) (2)转移到标号处执行指令 (IP)=(IP)+16位位移 #相当于 push IP jmp near ptr 标号 注释: (1)16位位移 = “标号”处的地址 - call指令后的第一个字节的地址 (2)16位位移的范围是 -32768 ~ 32767,用补码表示 (3)16位位移由编译程序再编译时算出 (2)指令“call far ptr 标号”实现的时段间转移 call far ptr 标号相当于 push CS push IP jmp far ptr 标号指令“call 标号”类似于“jmp near ptr 标号”,对应的机器指令中为对应于当前IP的转移位移,而不是转移的目的地址,实现段内转移; 指令“call far ptr 标号”实现段间转移。 (3)转移地址在寄存器中的call指令指令格式:call 16位寄存器 相当于进行 push IP jmp 16位寄存器 (4)转移地址在内存中的call指令call word ptr 内存单元地址 相当于: push IP jmp word ptr 内存单元地址示例: mov sp:10h mov ax,0123h mov ds:[0],ax call word ptr ds:[0] 执行后,(IP)= 0123h,(SP) = 10h-2 = 0ehcall dword ptr 内存单元地址 相当于 push CS push IP jmp dword ptr 内存单元地址示例: mov 10h mov ax,0123h mov ds:[0],ax ;低地址放偏移地址 mov word ptr ds:[2],0 ;高地址放段地址 call dword ptr ds:[0] 执行后,(CS)= 0,(IP)= 0123h,(SP)= 0ch 3、返回指令:ret和retf ret指令retf指令功能用栈中的数据,修改IP的内容,从而实现近转移用栈中的数据,修改CS和IP的内容,从而实现远转移相当于pop IPpop IP pop CS 举例示例1示例2 ;示例1 ;p6-1.asm assume cs:code,ss:stack stack segment db 16 dup(0) stack ends code segment mov ax,4c00h int 21h start: mov ax,stack mov ss,ax mov sp,16 mov ax,0 push ax mov bx,0 ret code ends end start6.6、call和ret的配合使用 1、具有子程序的源程序框架 assume cs:code code segment main:... call sub1 ;调用子程序sub1 ... mov ax,4c00h int 21h sub1:... call sub2 ;调用子程序2 ... ret sub2:... ... ret code ends end main 2、应用 ;示例 ;计算2的N次方方,计算前,N的值由CX给出 ;p6-3 assume cs:code,ss:stack stack segment db 16 dup(0) stack ends code segment start: mov ax,stack mov ss,ax mov sp,16 mov ax,1 mov cx,3 call s mov ax,4c00h add 21h s:add ax,ax loop s ret code ends end start
6.7、mul指令 1、格式 mul 寄存器 mul 内存单元 8位乘法16位乘法被除数ALAX除数8位寄存器或内存字节单元16位寄存器或内存字单元结果AXDX(高位)、AX(低位)示例mul bl --(ax)=(al)*(bl)
mul byte ptr ds:[0] --(ax)=(al)*((ds)*16+0) mul word ptr [bx+si+8] --(ax)=(ax)*((ds)*16+(bx)+(si)+8)结果的低16位 --(dx)=(ax)*((ds)*16+(bx)+(si)+8)结果的高16位 2、应用 示例1 ;计算100*10 mov al,64 ;100(O) = 64(H) mov bl,a ;10(O) = a(H) mul bl示例2 ;计算100*10000 mov ax,64 ;100 = 64(H) mov bx,2710 ;10000 = 2710(H) mul bx 6.8、汇编语言的模块化程序设计 1、参数和结果传递的问题 方案 用寄存器传递参数 用内存单元进行参数传递 用栈传递参数 (1)用寄存器来存储用寄存器来存储参数和结果是最常用使用的方法 编译任务:计算data段中第一组数据的3次方,结果保存在后面一组dword单元中。 0123456789ABCDEF 12345678 ;p6-4.asm ;by c10udz assume cs:code,ds:data,ss:stack stack segment db 16 dup(0) stack ends data segment dw 1,2,3,4,5,6,7,8 dd 0,0,0,0,0,0,0,0 data ends code segment start: mov ax,stack mov ss,ax mov sp,16 mov ax,data mov ds,ax mov si,0 mov di,16 mov cx,8 s:mov bx,[si] call cube mov [di],ax mov [di].2,dx add si,2 add di,4 loop s cube:mov ax,bx mul bx mul bx ret mov ax,4c00h int 21h code ends end start6.9、寄存器冲突问题 1、子程序标准框架 子程序开始:子程序中使用的寄存器入栈 子程序内容 子程序中使用的寄存器出栈 返回(ret、retf) 2、示例1编程将给出的数据改为大写格式 1)源码 ;p6-9.asm assume cs:code,ds:data,ss:stack data segment db 'word',0 db 'unix',0 db 'wind',0 db 'good',0 data ends stack segment db 16 dup(0) stack ends code segment start:mov ax,data mov ds,ax mov ax,stack mov ss,ax mov sp,16 mov bx,0 mov cx,4 s:mov si,bx call capital add bx,5 loop s mov ax,4c00h int 21h capital:push cx push si s0:mov cl,[si] mov ch,0 jcxz ok and byte ptr [si],11011111b inc si jmp short s0 ok:pop si pop cx ret ;子程序 code ends end start 2)查看源码
6.10、标志寄存器 1、标志(flag)寄存器的结构 PSW/FLAGS、别称:程序状态字 1514131211109876543210------------OFDFIFTFSFZF---AF---PF---CF
flag寄存器是按位起作用的,它的每一位都有专门的含义,记录特定的信息 2、标志寄存器的作用作用1)用来存储相关指令的某些执行结果 2)用来为CPU执行相关指令提供行为依据 3)用来控制CPU的相关工作方式 3、标志寄存器值得解读pushf:将标志寄存器的值压栈 popf:从栈中弹出数据,送入标志寄存器中。 5、各个标志详解 5.1、ZF-零标志(Zero Flag)ZF标记相关指令的计算结果是否为0 1)ZF=1,表示“结果为0”,1表示逻辑真 2)ZF=0,表示“结果非0”,0表示逻辑假 5.2、PF-奇偶标志(Parity Flag)PF记录指令执行后,结果的所有二进制位中1的个数 1)1的个数是偶数,PE=1 2)1的个数是奇数,PE=0 指令执行结果mov al,1 add al,10 结果为0000 1011B = 0000 0001B + 0000 1010B 其中有3个1,则PF=0 mov al,1 or al,2 结果为0000 0011B = 0000 0001B or 0000 0010B 结果中有2个1,则PF=1 5.3、SF-符号标志(Sign Flag)SF记录指令执行后,将结果视为有符号数 1)结果为负,SF=1 2)结果为非负,SF=0
另外:有符号数与补码 计算机中有符号数一律使用补码来表示和存储 1)正整数的补码使用二进制表示,与原码相同 2)负数的补码,将其对应的正数二进制的所有位取反,后加一 5.4、CF-进位标志(Carry Flag)在进行无符号数运算时,CF记录了运算结果的最高有效位向更高位的进位值,或从更高位的借位值。 CF记录指令执行后, 1)有进位或借位,CF=1 2)无进位或借位,CF=0 5.5、OF-溢出标志(Overflow Flag)在进行有符号数运算的时候,如果结果超过了机器所能表示的范围称为溢出。 OF记录有符号数操作指令执行后, 1)有溢出,OF=1 2)无溢出,OF=0
另外,CF和OF的区别 1)CF是对无符号数运算有意义的进/借位标志位 2)OF是对有符号数运算有意义的溢出标志位 6、综合一条指令会带来多个标志寄存器的变化 指令CFOFSFZFPFsub al,al00011mov al,10h00011add al,90h00101mov al,80h00101add al,80h11011mov al,0FCh11011add al,05h10000mov al,7Dh10000add al,0Bh01101
6.11、带进位的加减法 1、adc指令 adc是带进位加法指令,它利用CF位上记录的进位值 1)格式:adc 操作对象1,操作对象2 2)功能:操作对象1 = 操作对象1 + 操作对象2+CF 3)例:adc ax,bx实现的功能是:(ax)=(ax)+(bx)+CF 指令mov al,98H add al,al adc al,3 mov ax,1 add ax,ax adc ax,3 mov ax,2 mov bx,1 sub bx,ax adc ax,1 结果(al)=34H(ax)=5(ax)=4解释=(al)+3+CF =30H+3+1=34H =(ax)+3+CF =2+3+0=5 =(ax)+1+CF =2+1+1=4 2、应用(大数相加)例如:编程计算1EF000H + 201000H,结果放在ax(高16位)和bx(低16位)中 mov ax,001E mov bx,F000 add bx,1000 adc,ax,0020结果:1E F000H + 20 1000H = 3F 0000H 3、sbb指令sbb是带进位减法指令,它利用CF位上记录的借位值 1)格式:sbb 操作对象1,操作对象2 2)功能:操作对象1 = 操作对象1 - 操作对象2 - CF 3)例:sub ax,bx实现的功能是:(ax)=(ax)-(bx)-CF 应用:对任意大的数据进行减法运算 例如:计算003E 1000H - 0020 2000H,结果放在ax,bx中 mov ax,003e mov bx,1000 sub ax,0020 sbb bx,2000
6.12、cmp和条件转移指令
6.13、条件转移指令应用 6.14、DF标志和串传送指令
|
CopyRight 2018-2019 实验室设备网 版权所有 |