• 汇编入门学习笔记 (九)—— call和ret


    疯狂的暑假学习之  汇编入门学习笔记 (九)——  call和ret


    參考: 《汇编语言》 王爽 第10章


    call和ret都是转移指令。


    1. ret和retf


    ret指令:用栈中的数据,改动IP内容,从而实现近转移

    相当于:

    pop ip

    retf指令:用栈中的数据。改动CS和IP,从而实现远转移

    相当于:

    pop ip

    pop cs


    样例:ret

    assume cs:code,ss:stack
    
    stack segment
    	db 16 dup(1)
    stack ends
    
    code segment
    	mov ax,4c00H
    	int 21H
    
    start:	mov ax,stack
    	mov ss,ax
    	mov sp,16
    	
    	mov ax,0
    	push ax
    	ret
    	
    code ends
    
    end start

    retf

    assume cs:code,ss:stack
    
    stack segment
    	db 16 dup(1)
    stack ends
    
    code segment
    	mov ax,4c00H
    	int 21H
    
    start:	mov ax,stack
    	mov ss,ax
    	mov sp,16
    	
    	mov ax,0
    	push cs
    	push ax
    		
    	retf
    	
    code ends
    
    end start


    2. call指令


    call指令,运行操作:

        1.将当前IP或CS和IP压入栈中

        2.跳转


    (1)根据位移进行转移的call指令


    格式: call 标号


    将下一条的指令的ip压入栈中。在转到标号处


    相当于:


    push ip

    jmp near ptr 标号



    (2)转移的目的地址在指令中的call指令


    格式:

    call far ptr 标号


    将下一条的指令的CS和IP压入栈中。在转到标号处


    相当于:

    push cs

    push ip

    jmp far ptr


    (3)转移地址地址在寄存器中的call指令


    格式:call 16位reg


    相当于:

    push ip

    jmp 16位reg


    (4)转移地址在内存中的call指令

       1. call word ptr 内存单元

            相当于:

                 push ip

                 jmp word ptr 内存单元

       2. call dword ptr 内存单元

            相当于:

                  push cs

                  push ip

                  jmp dword ptr 内存单元


    3. mul 指令


    mul 是乘法指令


    表示两个数相乘,它必须是都是8位或者都是16位


    8位相乘 结果默认存放在ax中

    16位相乘 结果高位存放在dx中。低位存放在ax中

    样例见以下。



    3. call和ret配合使用


    call于ret结合使用。就相当于函数。 


    样例:求dw中数值的3次方。把bx当做“函数”參数,ax当做“函数”的返回值。

    assume cs:code,ds:data
    
    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,data
    		mov ds,ax
    		
    		mov si,0
    		mov di,16
    		mov cx,8
    	s:	mov bx,ds:[si]
    		call cube
    		mov ds:[di],ax
    		mov ds:[di+2],dx
    		
    		add si,2
    		add di,4
    		loop s
    			
    		mov ax,4c00H
    		int 21H
    			
    			
    	cube:	mov ax,bx
    		mul bx
    		mul bx
    		ret
    			
    				
    code ends
    
    end start


    寄存器数量有限,假设要传的參数。或者返回的參数过多。

    能够使用内存,或者栈。


    样例:小写转大写。(用内存存放參数)


    assume cs:code,ds:data
    
    data segment
    	db 'conversation'
    data ends
    
    code segment
    	start:	mov ax,data
    		mov ds,ax
    		
    		mov si,0
    		mov cx,12
    		call captial
    		
    		mov ax,4c00H
    		int 21H
    			
    captial:and byte ptr ds:[si],11011111b
    		inc si
    		loop captial
    			
    code ends
    
    end start


    样例:计算 (a - b) ^3  如果a=3,b=1 (用栈来存放參数)

    assume cs:code
    
    code segment
    	start:	mov ax,1
    		push ax
    		mov ax,3
    		push ax
    		call difcube
    		
    		mov ax,4c00H
    		int 21H
    		
    difcube:push bp
    		mov bp,sp
    		mov ax,[bp+4]
    		sub ax,[bp+6]
    		mov bp,ax
    		mul bp
    		mul bp
    		pop bp
    		
    		ret 4
    code ends
    
    end start


    上面代码中的 ret 4 表示:

    pop ip

    add sp,n


    样例:小写转大写,用0结尾来推断。(用栈来处理寄存器冲突)

    assume cs:code,ds:data
    
    data segment
    	db 'word',0
    	db 'city',0
    	db 'good',0
    data ends
    
    code segment
    	start:	mov ax,data
    		mov ds,ax
    		mov cx,3
    		
    		mov bx,0
    	s:	push cx
    		mov si,bx
    		call capital
    		add bx,5
    		pop cx
    		loop s
    			
    		mov ax,4c00H
    		int 21H
    			
    capital:mov cl,[si]
    		mov ch,0
    		jcxz ok
    		and byte ptr [si],11011111b
    		inc si
    		jmp short capital
    		ok:	ret		
    code ends
    
    end start

    注意:要用栈保存cx



    样例:实现show_str “函数”  在屏幕显示字符串。

    用dh指定函数 。dl指定列号,cl指定颜色

    assume cs:code,ds:data,ss:stack
    
    data segment
    	db 'Welcome to masm!',0
    data ends
    
    stack segment
    	dw 8 dup(0)
    stack ends
    
    code segment
    	start:	mov ax,data
    		mov ds,ax
    		mov ax,stack
    		mov ss,ax
    		mov sp,16
    		
    		mov dh,10  ;行
    		mov dl,17  ;列
    		mov cl,2   ;颜色
    		mov si,0
    		call show_str
    			
    		mov ax,4c00h
    		int 21h
    		
    show_str:	push ax
    		push di
    		push dx
    			
    		mov ax,10   ;确定行段 es
    		mul dh
    		add ax,0b800h
    		mov es,ax
    		
    		mov dh,0    ;确定列偏移 di,注意。一个字符两个字节
    		add dx,dx
    		mov di,dx
    			
    			
    	s: 	push cx    ;保存cx
    			
    		mov ch,0
    		mov cl,ds:[si]
    		jcxz ok      ;假设为0 跳转
    		
    		mov es:[di],cl
    		pop cx
    		mov es:[di+1],cl
    		
    		inc si
    		add di,2
    		jmp short s
    			
    			
    			
    	ok:	pop cx    ;不要忘记pop,眼不让rec还原的ip就不正确了
    		pop dx
    		pop di
    		pop ax
    		ret
    			
    
    code ends
    
    end start





  • 相关阅读:
    洛谷P4304 [TJOI2013]攻击装置 题解
    洛谷P2172 [国家集训队]部落战争 题解
    CentOS 7.0下配置MariaDB数据库
    读《深入php面向对象、模式与实践》有感(三)
    读《深入php面向对象、模式与实践》有感(二)
    读《深入php面向对象、模式与实践》有感(一)
    Linux下配置Lamp
    自己编写php框架(一)
    php读取html文件(或php文件)的方法
    Thinkphp框架感悟(二)
  • 原文地址:https://www.cnblogs.com/wzjhoutai/p/6713947.html
Copyright © 2020-2023  润新知