汇编简单入门教程(九)call和ret

您所在的位置:网站首页 汇编语言中ret 汇编简单入门教程(九)call和ret

汇编简单入门教程(九)call和ret

#汇编简单入门教程(九)call和ret| 来源: 网络整理| 查看: 265

 

参考: 《汇编语言》 王爽 第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

 

 

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3