现在的位置: 首页 > 综合 > 正文

(2011.11.02)汇编_王爽_第10章_学习小结

2013年08月19日 ⁄ 综合 ⁄ 共 3301字 ⁄ 字号 评论关闭

  

(2011.11.02)汇编_王爽_第10章_学习小结

本章内容:

1. call 与 ret指令的使用

2.使用call 和ret 对子程序的编写

3. mul指令(乘法)的使用

 

||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

 

知识点归纳:

       现在,个人根据段内转移和段间转移,在程序中调用方法的对应将其归纳为两类,主要功能是实现程序中子程序的编写,相当于高级语言中的函数调用,知识点如下:

 

一. 段内转移 (仅改IP)

 

       ->  指令:call 标号  \  call word ptr [内存单元地址]

              原理:实现段内转移原理相当于以下2个步骤

              第1步: push IP

              第2步: jmp near ptr 标号 \  jmp word ptr [内存地址]

 

       -> 指令:ret

              原理:改IP, 实现段内转移跳出,执行指令完毕后,让IP指向ret指令后的内存单元

                     第1步: pop IP

 

二. 段间转移 (改CS:IP)

 

         -> 指令:call far ptr 标号  \  call dword ptr [内存单元地址]

              原理:实现段间转移原理相当于以下3个步骤

                     第1步: push CS

                     第2步: push IP

                      第3步: jmp far ptr 标号  \  jmp dword ptr [内存单元地址]

 

       -> 指令:retf

              原理:实观段间转移跳出原理相当于以下2个步骤

                   第1步:pop IP

                   第2步:pop CS

 

三:具有子程序的源程序的框架

assume cs:code

code segment

main:                   ; 这个程序,两个子程序嵌套了

     :                   ; 一个子程序运行完后,接着会跳到另一个子程序运行

     :                   ; 最后都运行完后,会逐步跳出子程序,回到主程序

     call sub1           ; 现开始调用子程序

     :

     :

     mov ax, 4c00h

    int 21h

 

sub1 :                   ; 子程序sub1开始

      :

     :

     call far ptr sub2   ; 将子程序嵌套在sub1中,调用子程序sub2

     :

     ret                 ; 子程序返回

 

sub2:                                            ; 子程序sub2开始

     :                                           ; 为了不使寄存器发生冲突,还可以按以下方法编写子程序

     :                                           ; 子程序中使用的寄存器入栈

     :                                           ; 子程序内容

      :                                          ; 子程序中使用的寄存器出栈

     retf                                        ; 子程序返回

code ends

end main

 

||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

 

; 程序名称:1009_模块化程序设计_乘法的使用.asm

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

 

assume cs:code

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           ; 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:si指向下一个word单元

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

        loop s

        

        mov ax, 4c00h

        int 21h

        

    cube:                   ; 子程序cube(功能:计算三次方)

        mov ax, bx

        mul bx

        mul bx

        ret                 ; 乘法:mul指令    8位(数值小于255)    16位(数值大于等于255)

                                 ;        乘数1          al                    ax

                            ;        乘数2     8位(内存单元)或(reg) 16位(内存单元)或(reg)

                            ;        结果           ax                   dx:[ax] 

code ends

end start

 

||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

 

; 程序名称:1012_模块化程序设计_大小写转换_解决寄存器冲突的问题.asm

; 程序功能:将一个全是字母,以零结尾的字符串,转化为大写。

 

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             ; 每组单词的长度为5

        loop s

        

        mov ax, 4c00h

        int 21h

 

; 子程序说明:将一个全是字母,以零结尾的字符串,转化为大写

; 子程序参数:ds:si指向字符串的首地址

; 子程序结果:没有返回值

 

capital:                      ; 子程序中使用的寄存器入栈

        push cx               ; 这是为了防止影响主程序

        push si

 

change: 

        mov cl, [si]

        mov ch, 0

        jcxz ok               ; jcxz 当cx为零时,跳至标号

                                  ; 此处巧妙地利用了cl作为数据结束标记

        and byte ptr [si], 11011111b

        inc si

        jmp short change

        

ok:                           

        pop si                ; 寄存器按相应的顺序出栈,数值还原到主程序中。

        pop cx

        ret                   ; 跳出子程序

 

code ends

end start

        

 

||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

 

; 程序名称:实验10_编写子程序_显示字符串.asm

; 程序功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串

 

; 子程序描述:

; 名称:show_str

; 功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串

; 参数:(dh) = 行号(取值范围0~24),(dl) = 列号(取值范围 0~79),

;       (cl) = 颜色,  ds:si指向字符串的首地址

; 返回: 无

; 应用举例:在屏幕的8行3列,用绿色显示data段中的字符串

 

assume cs:code

 

data segment

    db 'Welcome to masm!', 0

data ends

 

code segment 

 

start:

        mov dh, 8       ; 行号

        mov dl, 3       ; 列号

        mov cl, 2       ; 颜色

        mov ax, data

        mov ds, ax      ; 将数据段地址放入至ds中

        mov si, 0       ; 将si设置为数据段的偏移地址

        

        call show_str

        

        mov ax, 4c00h

        int 21h

        

; 程序分析:

; 此处要实现显示功能,实际上就是要将ds:[si]的数据搬到B8000H - BFFFFH中

; 而现在,段地址我将其设为es = B8000, 偏移地址[bx = dh].[di = dl],循环时,di递增

 

show_str: 

        mov al, dh      ; 令[bx = dh]

        mov ah, 160      ; 每行160个字节

        mul ah

         sub ax, 160

        mov bx, ax

        mov al, dl      ; 令[di = dl]

        mov ah, 0

        mov di, ax

        mov ax, 0B800H ; 设置目的地址

        mov es, ax

        

      s:

        mov ch, [si]    ; 判断si中的数据是否为零

        mov cl, 0

        jcxz ok

        

        mov al, ds:[si]

        mov es:[bx+di], al 

        inc di

        mov ah, 2       ; 颜色

        mov es:[bx+di],ah

        

        inc di

        inc si        

        jmp short s

        

      ok:

        ret

        

code ends

end start

抱歉!评论已关闭.