当前位置:   article > 正文

汇编语言—流程转移和子程序_汇编语言调用子程序时,cs和ip会改变嘛

汇编语言调用子程序时,cs和ip会改变嘛

综述

  • 一般情况下指令是顺序地逐条执行的,而在实际中,常需要改变程序的执行流程
  • 可以修改IP,或同时修改CS和IP的指令
    在这里插入图片描述

offset 指令

  • 获取标号的偏移地址
  • offset 标号
  • 例:
    assume cs:codeseg
    codeseg segment
    start: mov ax,offset start     ;相当于mov ax,0
        s: mov ax,offset s         ;相当于mov ax,3
    codeseg ends
    end start
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

jmp 无条件转移

  • 无条件转移,可以只修改IP,也可以同时修改CSIP
  • jmp指令要给出两种信息
    在这里插入图片描述
  • 常见指令中的立即数均在指令中有体现
    在这里插入图片描述
    在这里插入图片描述
  • 如果是jmp指令
    076A:0000 B80000   MOV AX,0000
    076A:0003 EB05     JMP 000A     ;EB05 + 0005 = ...A
    076A:0005 050100   ADD AX,0001
    076A:0008 90       NOP
    076A:0009 90       NOP
    076A:000A 40       INC AX
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
两种段内转移
  • 短转移 jmp short 标号
    -128~127 = "标号"处的地址 - jmp指令后的第一个字节的地址
    assume cs:codesg
    codesg segment
    	start: mov ax,0
    	       jmp short s
    	       add ax,1
    	    s: inc ax
    codesg ends
    end start
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 近转移 jmp near ptr 标号
    -32769~32767 = "标号"处的地址 - jmp指令后的第一个字节的地址
    near ptr指明了相对于当前IP的转移位移,而不是转移的目的地址
    assume cs:codesg
    codesg segment
    start: mov ax,0
    	   mov bx,0
    	   jmp near ptr s
    	   db 256 dup (0)
    	s: add ax,1
    	   inc ax
    codesg ends
    end start
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 远转移 jmp far ptr标号
    far ptr指明了跳转到的目的地址,即包含了标号的段地址CS和偏移地址IP
    assume cs:codesg
    codesg segment
    start: mov ax,0
    	   mov bx,0
    	   jmp far ptr s
    	   db 256 dup (0)
    	s: add ax,1
    	   inc ax
    codesg ends
    end start
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 转移地址在寄存器中的jmp指令
    jmp 16位寄存器
    assume cs:codesg
    codesg segment
    start: mov ax,0
    	   mov bx,ax
    	   jmp bx
    	   mov ax,0123H
    codesg ends
    end start
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 转移地址在内存中的jmp指令
    段内转移jmp word ptr内存单元地址
    从内存单元地址处开始存放着一个字,是转移的目的偏移地址
    在这里插入图片描述
    段间转移jmp dword ptr内存单元地址
    从内存单元地址处开始存放着两个字,高地址处的字是转移的目的段地址,低地址处是转移的目的偏移地址
    在这里插入图片描述
    在这里插入图片描述

其它转移指令

jcxz

在这里插入图片描述

assume cs:codesg
codesg segment
start: mov ax,2000H
       mov ds, ax
       mov bx,0
    s: mov cx, [bx]
       jczx ok
       inc bx
       inc bx
       jmp short s
   ok: mov dx,bx
       mov ax,4c00H
       int 21H
codesg ends
end start 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

loop指令

在这里插入图片描述

call指令和ret指令

  • 调用子程序:call指令
  • 返回:ret指令
  • 实质:修改IP,或同时修改CS和IP
call标号
  • CPU执行call指令,进行两步操作:
    将当前的IP或CS和IP压入栈中
    转移到标号处执行指令
  • call标号
    16位位移=标号处的地址 - call指令后的第一个字节的地址
    16位位移的范围为-32768~32768,用补码表示
  • call标号类似jmp near ptr 标号,对应机器指令中为相对于当前IP的转移位移,而不是转移的目的地址,实现段内转移
      mov ax,0
      call s
      mov ax,4c00h
      int 21h
    
    s:add ax,1
      ret
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
call far ptr 标号 实现的是段间转移
  • "call far ptr"相当于
    push CS
    push IP
    jmp far ptr 标号
      mov ax,0
      call far ptr s
      ...
      mov ax,4c00h
      int 21h
    
    s:add ax,1
      ret
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
转移地址在寄存器中的call指令
  • 指令格式
    call 16位寄存器
  • 相当于
    push IP
    jmp 16位寄存器
    mov ax,0
    call ax
    ...
    mov ax,4c00h
    int 21h
    
    • 1
    • 2
    • 3
    • 4
    • 5
转移地址在内存中的call指令
  • call word ptr内存单元地址
    mov sp,10h              ;栈顶指针寄存器,当放入转移地址后,栈顶指针会向下偏移一个字
    mov ax,0123h
    mov ds:[0],ax
    call word ptr ds:[0]
    
    执行后,(IP)=0123H,(sp)=0EH
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • call dword ptr 内存单元地址
    mov sp,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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
ret和retf

在这里插入图片描述

call和ret的配合使用

具有子程序的源程序的框架
assume cs:code
code segment
main: ...
      call sub1
      ...
      mov ax,4c00h
      int 21h
sub1: ...
	  call sub2
	  ...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
为call和ret指令设置栈
assume cs:code ss:stack
stack segment
		db 8 dup (0)
		db 8 dup (0)
stack ends

code segment
start: mov ax,stack
	   mov ss,ax
	   mov sp,16
	   mov ax,1000
	   call s
	   mov ax,4c00h
	   int 21h
	s: add ax,ax
	   ret
code ends
end start
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/486928
推荐阅读
相关标签
  

闽ICP备14008679号