实验五 循环结构及子程序

五、实验步骤

1、请自行编写或上述参考代码,补充重要操作注释,编译链接执行、详细记录各操作步骤并截图。

1)编制在屏幕上显示九九乘法表的程序。

1. 用文字编辑工具(记事本或EDIT)将源程序输入,其扩展名为jiujiu.ASM。将源文件放到Dosbox挂载的目录下面。

源程序:

;定义数据段

DATA SEGMENT

S2 DB ?              

S1 DB ?              

X DB 1               ;定义变量X,值为1

Y DB 1               ;定义变量Y,值为1

S DB 0AH          ;定义变量S,值为0AH

FCH=2AH          ;定义常量FCH,值为2AH

FDH=3DH          ;定义常量FDH,值为3DH

FKG=20H           ;定义常量FKG,值为20H

FHH=0AH          ;定义常量FHH,值为0AH

FHC=0DH           ;定义常量FHC,值为0DH

DATA ENDS

 ;定义堆栈段,大小为20H,初始值为0

STACK1 SEGMENT STACK

DB 20H DUP(0)       

STACK1 ENDS

;定义代码段

CODE SEGMENT

ASSUME CS:CODE,DS:DATA,SS:STACK1

START:MOV AX,DATA     ;将数据段地址存入AX寄存器中

MOV DS,AX            ;将AX寄存器中的地址存入DS寄存器中

MOV CL,9             ;赋值9给CL寄存器

;循环Y次

LL1:

PUSH CX              ;将CL压入堆栈段

MOV CL,Y             ;将Y的值存入CL寄存器中

LL2:

CALL L1              ;调用子程序L1

INC X                ;x++

LOOP LL2             ;循环执行LL2,直到CX寄存器的值为0

MOV X,1              ;x=1

INC Y                ;Y++

MOV DL,FHH           ;输出换行和回车

MOV AH,2

INT 21H

MOV DL,FHC

MOV AH,2

INT 21H

POP CX               ;从堆栈段中取出CL

LOOP LL1             ;循环执行LL1,直到CX寄存器的值为0

MOV AH,4CH           ;程序结束

INT 21H

L1 PROC              ;计算X*Y=Z并且输出X*Y=Z的子程序

MOV DL,X             ;将X的值存入DL寄存器中

ADD DL,30H           ;将DL寄存器中的值加30H,转换成ASCII码字符

MOV AH,2             ;将输出函数号码存入AH寄存器中

INT 21H              ;调用输出函数

MOV DL,FCH           ;将FCH常量的值存入DL寄存器中

MOV AH,2            

INT 21H             

MOV DL,Y             ;将Y的值存入DL寄存器中

ADD DL,30H           ;将DL寄存器中的值加上30H,转换成ASCII码字符

MOV AH,2           

INT 21H              

MOV DL,FDH           ;将FDH常量的值存入DL寄存器中

MOV AH,2             

INT 21H             

MOV AL,X             ;将X的值存入AL寄存器中

MUL Y                ;将AL寄存器中的值乘Y,并将结果存入AX寄存器中

DIV S               ;将AX寄存器中的值除S的值,并将商存入AL寄存器中,余数丢弃

MOV S1,AH            ;将AX寄存器中的余数部分存入S1变量中

ADD AL,30H           ;将AL寄存器中的值加上30H,转换成ASCII码字符

MOV DL,AL

MOV AH,2

INT 21H

ADD S1,30H  ;将s1加上30H,转换成ASCII码字符

MOV DL,S1

MOV AH,2

INT 21H

MOV DL,FKG           ;输出空格

MOV AH,2

INT 21H

RET

L1 ENDP              ;子程序结束

CODE ENDS

END START

图5-1更改扩展名为jiujiu.ASM

  1. 用MASM对源文件进行汇编,产生OBJ文件和LST文件。

图5-2 MASM对源文件进行汇编

图5-3 OBJ文件和LST文件

  1. 用LINK将.OBJ文件连接成可执行的.EXE文件。

图5-4 link语句执行过程

图5-5 LINK将.OBJ文件连接成可执行的.EXE文件

4. 在DOS状态下运行LINK产生的.EXE文件。

图5-6 运行结果

2) 编制在屏幕上显示用*组成的三角形的程序。

1. 用文字编辑工具(记事本或EDIT)将源程序输入,其扩展名为sanjiao.ASM。将源文件放到Dosbox挂载的目录下面。

源程序:

DATA SEGMENT ; 数据段

N DB ? ; 存储输入的行数

FCH=2AH ; '*' 的 ASCII 码

FDH=3DH ; '=' 的 ASCII 码

FKG=20H ; ' ' 的 ASCII 码

FHH=0AH ; 换行的 ASCII 码

FHC=0DH ; 回车的 ASCII 码

DATA ENDS             ;数据段结束

STACK1 SEGMENT STACK

DB 20H DUP(0)

STACK1 ENDS

 CODES SEGMENT   ;定义代码段     

ASSUME CS:CODES,DS:DATA

START:               

MOV AX,DATA ;将数据段地址存入AX寄存器中

MOV DS,AX

MOV AH,1            ;输入一位16进制数确定输出行数

INT 21H

CMP AL,39H ;判断输入的数是否小于等于39H

JBE L1 ;如果是,跳转到L1标签;如果不是,将输入的数减去7,得到对应的行数

SUB AL,07H

L1:

SUB AL,30H

MOV N,AL

XOR BX,BX ;清零BX寄存器

MOV DL,FCH

MOV CL,N

MOV DL,FHH          ;输出换行和回车

MOV AH,2

INT 21H

MOV DL,FHC

MOV AH,2

INT 21H

LOP:PUSH CX ;将CX寄存器的值压入堆栈段中

INC BL ;将BL寄存器的值加1

MOV CL,BL

MOV DL,FCH

LOP2:MOV AH,02H

INT 21H

LOOP LOP2 ;循环执行LOP2,直到CX寄存器的值为0

POP CX ;从堆栈段中取出CX寄存器的值

MOV DL,0AH ;输出换行符和回车符

MOV AH,02H

INT 21H

MOV DL,FHC ;输出空格字符和回车符

MOV AH,02H

INT 21H

CMP BL,9 ;判断BL寄存器的值是否为9

JZ L2 ;如果是,跳转到L2标签;如果不是,继续执行LOP循环

LOOP LOP

L2:MOV AH,4CH            ;程序结束

INT 21H

CODES ENDS

END START

图5-7更改扩展名为sanjiao.ASM

  1. 用MASM对源文件进行汇编,产生OBJ文件和LST文件。

图5-8 MASM对源文件进行汇编

图5-9 OBJ文件和LST文件

  1. 用LINK将.OBJ文件连接成可执行的.EXE文件。

图5-10 link语句执行过程

图5-11 LINK将.OBJ文件连接成可执行的.EXE文件

4. 在DOS状态下运行LINK产生的.EXE文件。

图5-12 运行结果

2、(选做)自行编写杨辉三角输出代码,补充重要操作注释,编译链接执行、详细记录各操作步骤并截图。

1. 用文字编辑工具(记事本或EDIT)将源程序输入,其扩展名为yanghui.ASM。将源文件放到Dosbox挂载的目录下面。

源程序:

STACK1 SEGMENT STACK ;堆栈段

DB 20H DUP(0)

STACK1 ENDS        

CODE  SEGMENT ;代码段

ASSUME    CS:CODE,DS:CODE

      ORG       100H

      START:  JMP     BEGIN

      MESSAGE  DB        13,10,9,'n(1~9): $' ;输入1~9之间任意一个数 将会生成n行杨辉三角

      BEGIN:

              PUSH      CS

              POP        DS

              MOV      DX,OFFSET MESSAGE       ;提示上面的输入信息:n(1~9):

              MOV      AH,9

              INT         21H

              CALL       GETMESSAGE        ;调用输入程序

              CMP       BP,10       ;输入的数和10作比较

              JBE         GO        ;小于等于10跳转至GO

       GO:

              MOV     AX,0E0DH

              INT       10H

              MOV     AL,0AH

              INT       10H

              PUSH    BP

              CALL     YANGHUI ;调用输出n行杨辉三角

        GETMESSAGE PROC                  ;输入n 程序

              PUSH      CX

              PUSH      BX

              XOR        BP,BP

              MOV       BX,10

              MOV       CX,2

      INPUTME:

              MOV       AH,0        ;键盘输入数据

              INT         16H

              CMP       AL,0DH     ;回车结束输入

              JZ           OK

              CMP       AL,'1'      ;限制输入1~9

              JB           INPUTME

              CMP       AL,'9'

              JA          INPUTME

              MOV      AH,0EH     

              INT        10H

              SUB       AL,31H      ;转化ASCII为16进制

              CBW                   ;字节扩展为字

              XCHG      AX,BP

              MUL        BX          ;扩大10倍

              ADD        BP,AX     

              LOOP      INPUTME

         OK:  NOP                   ;数值结果在BP中

;恢复用到的寄存器

              POP       BX

              POP       CX

              RET

        GETMESSAGE  ENDP

; 输出N行杨辉三角

       YANGHUI:

              MOV       BP, SP

              MOV       AX, [BP+2]  ; 保存N到AX

              SHR         AX, 1       ; N = N / 2

              PUSH       AX

              MOV       AX, [BP+2]  ; 保存N到AX

              PUSH      AX

              CALL       C         ; C(N, N/2)获取最后一行中间的那个值,即最大值

              CALL       GETDIMAX    ; 计算最大值的长度

              MOV      CX, AX      

              XOR       DI, DI      ; 外层循环输出每一行

              JMP       LOOP1

        UPDI:

              INC       DI          ; 更新DI

        LOOP1:

              CMP       DI, [BP+2]  ; 循环N次

              JG           RE

              MOV      AX, [BP+2]  ; 计算行前空格数' ' = (N-i)*CL

              SUB        AX, DI

              MUL       CL ;CL是最大长度

              CALL       SHOWYVSPACE   ; 输出行前空格

              XOR        SI, SI     ; 内层循环输出一行中的每个数

              JMP        LOOP2

        UPSI:

              INC       SI          ; 更新SI

        LOOP2:

              CMP       SI, DI      ; 循环DI次

              JG          ENTER

              PUSH     SI

              PUSH     DI

              CALL      C           ; 获取该行的位于SI位置的组合数,调用C(DI, SI)

              PUSH      AX          ; 保存该组合数

              CALL       SHOWYV        ; 输出该组合数

              MOV       AX, CX      ;输出数字间空格,个数 = N - 1

              SUB        AX, 1       ;

              CALL       SHOWYVSPACE   ;

              POP        AX          ;

              CALL       GETDIMAX    ;获取该组合数长度

              MOV       BX, AX      ;

              MOV       AX, CX      ;

              SUB         AX, BX   ;需要填充的空格数 = 最大长度 - 该数长度 + 1

              ADD       AX, 1       ;

              CALL       SHOWYVSPACE   ;

              JMP        UPSI         ; 更新内层循环

      ENTER:                    ; 实现换行     

              MOV       AH, 2     

              MOV       DL, 13

              INT          21H

              MOV       DL, 10

              INT          21H

              JMP         UPDI         ; 更新外层循环

      RE:                    

              RET       2           ; 释放栈

; { C(n, m) = 1 (n < m 或 m = 0)

; { C(n, m) = C(n-1, m-1) + C(n-1, m) (n > m)

          C:

              PUSH      BP

              MOV       BP, SP

              SUB         SP, 2       

              MOV       BX, [BP+6]  ; 保存m到BX

              CMP       BX, [BP+4]  ; 如果m > n 返回1

              JZ           RETURN1

              CMP       BX, 0       ; 如果m = 0 返回1

              JZ           RETURN1

              MOV       AX, [BP+4]  ; 保存n到AX

              DEC         AX          ; AX--

              DEC         BX          ; BX--

              PUSH      BX

              PUSH      AX

              CALL       C           ; 返回上一行左边的那个数

              MOV       [BP-2], AX  ; 保存上一行左边的数

              MOV       AX, [BP+4]  ; 返回上一行右边的数

              DEC         AX

              PUSH      [BP+6]

              PUSH      AX

              CALL       C

              ADD        AX, [BP-2]  ; 和左上的数相加得出该组合数

              JMP        RES

         RETURN1:

              MOV       AX, 1

         RES:

              MOV       SP, BP

              POP         BP

              RET          4           ; AX返回组合数

; 递归输出AX

; 求出余数,AX = AX / 10

; AX = 0时退出,开始逆序输出求出的各位余数

       SHOWYV:

              MOV       BX, 10

              CMP       AX, 0

              JZ           OK1

              DIV         BL

              PUSH      AX

              AND       AX, 00FFH

              CALL      SHOWYV

              POP       DX

              MOV     DL, DH

              OR        DL, 30H

              MOV    AH, 2

              INT       21H

        OK1:

              RET

; 获取一个数的长度,AX为参数

   GETDIMAX:

              MOV       BX, 10

              XOR        DX, DX

       NEXT:

              CMP       AX, 0

              JLE         OK2

              DIV        BL

              AND      AX, 0FFH

              INC       DX

              JMP      NEXT

        OK2:

              MOV       AX, DX

              RET

; 输出AX个空格

  SHOWYVSPACE:

              MOV       BX, AX

              MOV       AH, 2

              MOV       DL, ' '

      NEXTS:

              CMP       BX, 0

              JLE          OVER

              INT         21H

              DEC        BX

              JMP        NEXTS

      OVER:

              RET

        CODE  ENDS

              END       START

图5-13更改扩展名为sanjiao.ASM

  1. 用MASM对源文件进行汇编,产生OBJ文件和LST文件。

图5-14 MASM对源文件进行汇编

图5-15 OBJ文件和LST文件

  1. 用LINK将.OBJ文件连接成可执行的.EXE文件。

图5-16 link语句执行过程

图5-17 LINK将.OBJ文件连接成可执行的.EXE文件

4. 在DOS状态下运行LINK产生的.EXE文件。

图5-18 运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

cwn_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值