(重点)call和ret的配合

(重点)call和ret的配合

1.0 call和ret

  • call和ref都是转移指令,他们都只会修改ip,或者同时修改cs:ip

1.1 ret 指令

  • ret执行使用栈中的数据,修改ip的内容,从而实现近转移

  • cpu执行ret指令时 会进行两步操作

    • 先pop 数据 把pop的数据赋值给ip
    • 在将sp+2,将指针指向栈顶 相当于 pop ip
  • assume cs:code,ss:stack
    
    stack segment
    	db 16 dup (5)
    stack ends
    
    code segment
    		mov ax, 4c00H
    		int 21H
    start:	mov ax, stack
    		mov ss, ax
    		mov sp, 16			;设置栈顶
    		mov ax, 0			
    		
    		push ax				;将ax入栈
    		
    		ret 				;等同与pop ip  将取出的数据给到ip		
    code ends
    end start
    

1.2 rerf 指令

  • retf用栈中数据,修改cs:ip的值 实现原远转移

  • cpu执行retf指令时 会进行两步操作

    • pop 数据 把pop的数据赋值给ip
    • 在将sp+2,将指针指向栈顶 相当于 pop ip
    • pop 数据 把pop的数据赋值给cs
    • 在将sp+2,将指针指向栈顶 相当于 pop cs
  • assume cs:code,ss:stack
    
    stack segment
    	db 16 dup (5)
    stack ends
    
    code segment
    		mov ax, 4c00H
    		int 21H
    start:	mov ax, stack
    		mov ss, ax
    		mov sp, 16			;设置栈顶
    		mov ax, 0
    		
    		push cs				;将cs,ax入栈
    		push ax				
    		
    		retf				;pop ip     pop cs
    code ends
    end start
    

1.3 call指令

  • call 指令经常和ret配和使用,因此cpu执行call指令进行两步操作

    • call将当前IP或CS:IP压栈
    • 转移(jmp)
  • call指令不能进行短转移

  • 用法:

  • assume cs:code
    
    code segment
    	
    start:	mov ax, 0 
    		call s
    
    		mov ax, 4c00H
    		int 21H
    		
    	s:	add ax, 1
    	
    		ret	
    code ends
    end start	
    
  • 相当于进行

    • push ip 将ip入栈
    • jmp near ptr 标号 相对当前进行16位的位移
  • call far ptr 标号实现的是段间转移相当于进行

    • push cs
    • push ip
    • jmp far ptr 标号
  • call 寄存器

  • call 内存地址

    • call word ptr ds:[0]
    • call dword ptr ds:[0]

1.4 call和ret实现子程序

  • 可以设置ax的值,利用cx 来实现ax的几次方

  • assume cs:code 
    
    code segment
    start:	mov ax, 1
    		mov cx, 5
    		
    		call s
    		mov ax, 4c00H
    		int 21H
    		
    	s:	add ax, ax
    		loop s
    		ret
    code ends
    end start
    
  • call指令后面的指令地址存储在栈中,所以可以在子程序后使用ret指令,用栈中的数据值设置ip的值。从而转到call指令后的代码继续执行

  • 例如

1.5 mul指令 乘法

  • 相乘的两个数 要么都是八位,要么都是16位

  • 结果

    • 8位: AX中
    • 16位: DX高位 AX地位
  • 计算100*10

  • assume cs:code 
    
    code segment
    start:	mov al,100
    		mov bl,10
    		
    		mul bl   		;结果存储到AX中
    code ends
    end start
    
  • 计算100*10000

  • assume cs:code 
    
    code segment
    start:	mov ax,100
    		mov bx,10000
    		
    		mul bx   		;结果低位存储到AX中 结果高位存储到DX中
    code ends
    end start
    

1.6 模块话程序设计

  • ​ 因为现实问题一般比较复杂,一般进行分析的时候,将它们转化为相互连接 ,一个子程序完成一个功能

1.7 参数和结果的传送问题

  • 子程序一般处理一定的事务后,会将处理的数据返回给调用者,其实我们讨论参数和返回值传递的问题时,其实就是在探讨,该如何存储子程序需要的参数和产生的返回值
  • 我们在编程的时候要有良好的编程习惯,要对程序有详细的注释,来说明子程序的功能已经参数结果的说明
  • 可以利用寄存器来临时存放参数和结果

1.8 批量数据的传递

  • 寄存器的数量终究是有限制的,我们不可能简单的用寄存器来存放多个需要传送的值,对于返回值也是一样的问题

  • 编程 例子

  • assume cs:code,ds:data
    
    data segment
    	db 'transition'
    data ends
    
    code segment
    start:		mov ax, data
    			mov ds, ax
    			
    			mov si, 0
    			mov cx, 10
    			call capital
    		
    			mov ax, 4c00H
    			int 21H
    	capital:and byte ptr [si],11011111B
    			inc si
    			loop capital
    			ret
    code ends
    
    end start
    
  • 我们还有一种通用的方法使用栈来传递参数

posted @ 2020-12-08 23:01  immortal_mode  阅读(326)  评论(0)    收藏  举报