汇编语言——第10章 CALL和RET指令

目录

引言

10.1 ret和retf

检测点10.1

10.2 call指令

10.3 依据位移进行转移的call指令

检测点10.2 

10.4 转移的目的地址在指令中的call指令

检测点10.3 

10.5 转移地址在寄存器中的call指令

检测点10.4 

10.6 转移地址在内存中的call指令

检测点 10.5

10.7 call和ret的配合使用

10.8 mul指令

10.9 模块化程序设计

10.10 参数和结果传递的问题

10.11 批量数据的传递

10.12 寄存器冲突的问题


引言

call和ret指令都是转移指令,他们都修改IP,或同时修改CS和IP。

它们经常被共同用来实现子程序的设计。

10.1 ret和retf

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

CPU执行ret指令时:

1(IP)=((ss)*16+(sp)),指向栈顶

2(sp)=(sp)+2

retf指令用栈中的数据,修改CSIP的内容,从而实现远转移。

CPU执行retf指令时:

1(IP)=((ss)*16+(sp))

2(sp)=(sp)+2

3(CS)=((ss)*16+(sp))

4(sp)=(sp)+2

用汇编的语法来解释retretf指令:

CPU执行ret指令相当于进行:pop IP

CPU执行retf指令相当于进行:pop IPpop CS

assume cs:code

 stack segment

    db 16 dup(0)

stack ends

code segment

              mov ax,4c00h

              int 21h

start:      mov ax,stack

              mov ss,ax

              mov sp,16

              mov ax,0

              push ax

              mov bx,0

              ret

code ends

end start

ret指令执行后,(IP)=0,CS:IP指向代码段的第一条命令。

assume cs:code

stack segment

   db 16 dup(0)

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

              mov bx,0

              retf

codesg ends

end start

 retf指令执行后,CS:IP指向代码段的第一条命令。

检测点10.1

10.2 call指令

call指令经常跟ret指令配合使用,CPU执行call指令时:

1、将当前的IP或者CS和IP压入栈;

2、转移(jmp)。

call指令除了不能实现短转移之外,call指令实现转移的方法和jmp指令的原理相同。

call指令实现段间的转移(远转移)或近转移。

10.3 依据位移进行转移的call指令

call标号(将当前的IP压入栈后转到目标处执行指令)

call执行此种格式的call指令时,进行以下操作:

(1)(SP)=(SP)-2
      ((SS)*16+(SP))=(IP)

(2)(IP)=(IP)+16位位移;

16位位移=标号处的地址-call指令后的第一个字节的地址。

16位位移的范围是-32768~32767,用补码表示。

16位位移由编译程序在编译时算出。

用汇编语法解释call指令:

push IP

jmp near ptr 标号

检测点10.2 

10.4 转移的目的地址在指令中的call指令

“call far ptr 标号”实现的是段间转移。

call执行此种格式的call指令时,进行以下操作:

(1)(sp)=(sp)-2

           ((ss)*16+(sp))=(CS)

         (sp)=(sp)-2

           ((ss)*16+(sp))=(IP)

(2)(CS)=标号所在段的段地址

       (IP)=标号所在段的偏移地址

用汇编语法解释call指令:

push CS

push IP

jmp far ptr 标号 

检测点10.3 

10.5 转移地址在寄存器中的call指令

指令格式是:call 16位reg

功能:

(1)(sp)=(sp)-2

(2)((ss)*16+(sp))=(IP)

(3)(IP)=(16位reg)

用汇编语法解释此种call指令,CPU执行“call 16reg”时,相当于:

push IP

jmp 16位reg

检测点10.4 

10.6 转移地址在内存中的call指令

 转移地址在内存中的call指令有两种格式:

(1)call word ptr 内存单元地址;段内跳转

用汇编语法解释call word ptr 内存单元地址:

       push IP

       jmp word ptr 内存单元地址

例子:

mov sp,10h

mov ax,0123H

mov ds:[0],ax

call word ptr ds:[0]

执行后,(IP)=0123H,(sp)=0EH.

(2) call dword ptr 内存单元地址;段间跳转

         用汇编语法解释call dword ptr 内存单元地址

       push CS

       push IP

       jmp word ptr 内存单元地址

         例子:

mov sp,10h

mov ax,0123H

mov ds:[0],ax

mov word ptr ds:[2],0

call dword ptr ds:[0]

   执行后,(CS)=0,(IP)=0123H,(SP)=0CH。 

检测点 10.5

10.7 call和ret的配合使用

10.8 mul指令

mul是乘法指令,使用mul做乘法的时候应注意以下两点:

(1)两个相乘的数:两个相乘的数,要么都是8位,要么都是16位。如果是8位,一个默认放在AL中,另一个放在8位reg或内存字节单元中;如果是16位,一个默认在AX中,另一个放在16位reg或内存字单元中。

(2)结果:如果是8位乘法,结果默认放在AX中;如果是16位乘法,结果高位默认在DX中存放,低位在AX中存放。

格式:

mull reg

mull 内存单元

内存单元可以用不同的寻址方式给出,比如:

mull byte ptr ds:[0]

含义:(ax)=(al)*((ds)*16+0);

mull word ptr [bx+si+idata]

含义:(ax)=(ax)*((ds)*16+(bx)+(si)+idata)结果的低6位。

  (dx)=(ax)*((ds)*16+(bx)+(si)+idata)结果的高6位。

例子: 

 (1)计算100*10

两个数都小于255,可以做8位乘法 

mov al,100

mov bl,10

mul bl

结果(ax)=1000(03E8H)

(2)计算100*1000

1000都大于255,要做16位乘法

mov ax,100

mov bx,10000

mul bx

结果(ax)=4240H(dx)=000FH,(F4240H=1000000)

10.9 模块化程序设计

calret指令共同支持汇编语言编程中的模块化设计。

10.10 参数和结果传递的问题

用寄存器来存储参数和结果是最常用的方法。对于存放参数的寄存器和存放结果的寄存器,调用者和子程序的读写操作恰恰相反:

调用者将参数送入参数寄存器,从结果寄存器中取到返回值;

子程序从参数寄存器中取到参数,将返回值送入结果寄存器。

编程:计算data段中第一组数据的3次方,结果保存在后面一组dword单元中

assume cs:code

 data segment

     dw 1,2,3,4,5,6,7,8

     dd 8 dup (0)

 data ends

code segment

   start:   mov ax,data

              mov ds,ax

              mov si,0                               ;ds:si指向第一组word单元

              mov di,16                             ;ds:di指向第二组dword单元

              mov cx,8

          s: mov bx,[si]

              call cube

              mov [di],ax

              mov [di].2,dx

              add si,2                                ;ds:di指向下一个word单元

              add di,4                                ;ds:di指向下一个dword单元

              loop s

              mov ax,4c00h

              int 21h

    cube: mov ax,bx

              mul bx

              mul bx

              ret

code ends

end start

10.11 批量数据的传递

将批量数据放在内存中,然后将它们所在内存空间的首地址放在寄存器中,传递给需要的子程序,批量数据的返回结果也是采用同样的方法。除此之外还可以用栈来传递参数。

编程:将data段中的字符串转化为大写

assume cs:code

data segment

    db 'conversation'

data ends

code segment

    start: mov ax,data

             mov ds,ax

             mov si,0                ;ds:si指向字符串(批量数据)所在空间的首地址

             mov cx,12             ;cx存放字符串的长度

             call capital

             mov ax,4c00h

             int 21h

capital: add byte ptr [si],11011111B

             inc si

             loop capital

             ret

code ends

end start

10.12 寄存器冲突的问题

编程:将一个全是字母,以0结尾的字符串转化为大写

capital: mov cl,[si]                               ;8

            mov ch,0                                 ;8位设置为0

            jcxz ok                                     ;如果(cx)=0则结束,如果不是0则处理

            and byte ptr [si],11011111B

            inc si

            jmp short capital

       ok: ret

编程:将data段中的字符串全部转化为大写

assume cs:code

data segment

    db  'word',0

    db  'unix',0

    db  'wind',0

    db  'good',0

data ends

此程序有bugcx有问题

assume cs:code

data segment

    db  'word',0

    db  'unix',0

    db  'wind',0

    db  'good',0

data ends

code segment

    start: mov ax,data

             mov ds,ax

             mov bx,0

             mov cx,4

        s:  mov si,bx

             call capital

             add bx,5

             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

  • 5
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

关了个尔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值