美文网首页
5.call和ret指令

5.call和ret指令

作者: 芝麻酱的简书 | 来源:发表于2018-08-02 10:58 被阅读17次
    屏幕快照 2018-08-02 10.57.29.png
    call和ret指令使用:
    assume cs:code, ds:data, ss:stack
    
    ; 栈段
    stack segment
        db 100 dup(0)
    stack ends  
    
    
    ; 数据段
    data segment 
        db 100 dup(0) 
        string db 'Hello!$'
    data ends
    
    
    ; 代码段
    code segment
    start:
        ; 手动设置ds、ss的值
        mov ax, data
        mov ds, ax
        mov ax, stack
        mov ss, ax  
        
        ; 业务逻辑 
        call print
        
        mov ax, 1122h
        mov bx, 3344h
        add ax, bx  
        
        ; 退出
        mov ax, 4c00h
        int 21h 
        
    ; 打印字符串    
    print:    
    
        ; ds:dx告知字符串地址    
        mov dx, offset string
        mov ah, 9h
        int 21h
        
        ret 
                    
    code ends  
    
    end start 
    
    ; 函数的要素
    ; 1.参数
    ; 2.返回值
    ; 3.局部变量
    

    实现函数返回值:

    demo1:使用ds

    assume cs:code ,ds:data ss:stack
    data segment
      db 100 dup(0)
    data ends
    
    code segment
    start:
          mov ax,data
          mov ds,ax
          call  returnFunc
          mov bx,[0]
    
    returnFunc :
          mov ax,2
          add ax,ax
          mov [0],ax
          ret
    code ends
    end start
    
    

    demo2:使用ds中的别名

    ...
    data segment
       ;定义别名result
       result dw 0
    data ends
    ...
    start:
          mov ax,data
          mov ds,ax
          call  returnFunc
          mov bx,result
    ...
    returnFunc :
          mov ax,2
          add ax,ax
          mov result,ax
          ret
    
    

    demo3:通用做法是返回值直接放在ax通用寄存器中


    实现函数传参:

    1.使用ax寄存器存储参数来实现传递
    2.使用栈来存储参数来传递,也是通用做法:

    • 使用bp来快速访问栈中数据
    • 使用mov sp指令来快速释放栈中数据
    assume cs:code, ds:data, ss:stack
    
    ; 栈段
    stack segment
        db 100 dup(0)
    stack ends  
    
    ; 数据段
    data segment  
        db 100 dup(0) 
    data ends
    
    ; 代码段
    code segment
    start:
        ; 手动设置ds、ss的值
        mov ax, data
        mov ds, ax
        mov ax, stack
        mov ss, ax  
        
        ; 业务逻辑
        push 1122h
        push 3344h 
        call sum3 
        add sp, 4
        
        push 2222h
        push 2222h 
        call sum3
        add sp, 4
            
        ; 退出
        mov ax, 4c00h
        int 21h 
        
    ; 返回值放ax寄存器
    ; 传递2个参数(放入栈中)    
    sum3:   
        ; 访问栈中的参数
        mov bp, sp
        mov ax, ss:[bp+2]
        add ax, ss:[bp+4]
        ret 
              
    ; 返回值放ax寄存器
    ; 传递2个参数(分别放ds:0、ds:2)    
    sum2:         
        mov ax, [0]
        add ax, [2]
        ret 
                
    ; 返回值放ax寄存器
    ; 传递2个参数(分别放cx、dx中)    
    sum1:  
        mov ax, cx
        add ax, dx
        ret 
                    
    code ends  
    end start
    ; 栈平衡:函数调用前后的栈顶指针要一致
    ; 栈如果不平衡的结果:栈空间迟早会被用完
    

    注意区分递归调用、函数内调用函数和连续调用多个函数对栈的使用的区别,
    函数内调用函数会一直往栈中压数据,而多函数连续调用,只会当前函数栈中数据释放后再继续下一个函数的压栈操作。


    栈平衡的方法:

    1.外平栈,函数外面进行平栈,也就是上面的操作,要是常用的做法
    2.内平栈,函数内进行平栈,函数内调用其他函数的时候:

    sum2:         
        mov ax, [0]
        add ax, [2]
        call sum1
        ret 
     
    sum1:  
        mov ax, cx
        add ax, dx
        ret 4
    

    相关文章

      网友评论

          本文标题:5.call和ret指令

          本文链接:https://www.haomeiwen.com/subject/akdjvftx.html