5.call和ret指令

2018-08-02  本文已影响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.使用栈来存储参数来传递,也是通用做法:

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
上一篇 下一篇

猜你喜欢

热点阅读