码迷,mamicode.com
首页 > 编程语言 > 详细

学习<<汇编语言 -王爽>>,自已完成的一道课程设计题 (5)

时间:2015-03-06 10:10:16      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:汇编   汇编语言   

课程设计1 (材料详见书上211页)


题目描述:

技术分享


以下是我解答的完整的代码:

:>----------------------------------------------------------------------------------------

assume cs:codesg, ss:stacksg


 datasg segment

     db ‘1975‘, ‘1976‘, ‘1977‘, ‘1978‘, ‘1979‘, ‘1980‘, ‘1981‘, ‘1982‘, ‘1983‘

     db ‘1984‘, ‘1985‘, ‘1986‘, ‘1987‘, ‘1988‘, ‘1989‘, ‘1990‘, ‘1991‘, ‘1992‘

     db ‘1993‘, ‘1994‘, ‘1995‘

     dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514

     dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000

     dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226

     dw 11542,14430,15257,17800

 datasg ends

 

 stacksg segment

   dw 16 dup(0)  ;栈-用来暂存数据

 stacksg ends


 mathsg segment

   db 16 dup(0)  ;用来保存十进制数对应的ASCII码值

 mathsg ends


 stringsg segment

   db 80 dup(20h)  ;定义字符串, 长度为一行, 用空格符初始化

 stringsg ends


 codesg segment

     start: mov ax, datasg

            mov ds, ax

            mov ax, stacksg

            mov ss, ax

            mov sp, 20h  ;初始化栈

            mov ax, stringsg

            mov es, ax

            mov bx, 0  ;增量为4个字节

            mov bp, 0  ;增量为2个字节

            mov cx, 21 ;总共要处理的行数

            mov dh, 0  ;指定显示的行

            mov dl, 0  ;指定显示的列

        p0: push cx  ;外层循环

            push dx

             ;----下面处理每行的日期数据

            mov cx, 4

            mov si, 0

            mov di, 0

        p1: mov al, ds:[bx][si]

            mov es:[di].2, al

            inc si

            inc di

            loop p1

             ;----下面处理每行的收入数据

            mov si, 2

            mov ax, ds:[bx].54h

            mov dx, ds:[bx][si].54h

            call dtoc

            push ds

            mov ds, di

            mov ch, 0

            mov di, 0

        p2: mov cl, ds:[si]

            jcxz p2end

            mov es:[di].10h, cl

            inc si

            inc di

            jmp p2

             ;----下面处理每行的雇员数据

     p2end: pop ds

            mov ax, ds:[bp].0A8h

            mov dx, 0

            call dtoc

            push ds

            mov ds, di

            mov ch, 0

            mov di, 0

        p3: mov cl, ds:[si]

            jcxz p3end

            mov es:[di].20h, cl

            inc si

            inc di

            jmp p3

             ;----下面处理每行的平均收入数据

     p3end: pop ds

            mov si, 2

            mov ax, ds:[bx].54h

            mov dx, ds:[bx][si].54h

            mov cx, ds:[bp].0A8h

            call divdw

            call dtoc

            push ds

            mov ds, di

            mov ch, 0

            mov di, 0

        p4: mov cl, ds:[si]

            jcxz p4end

            mov es:[di].30h, cl

            inc si

            inc di

            jmp p4

             ;----下面加上结束符,并且显示处理好的行内容

     p4end: pop ds

            mov di, 4Fh

            mov byte ptr es:[di], 0

             ;----运行到这里时已构造好一行的显示内容,存在stringsg段中

            

            pop dx

            mov cl, 07h

            mov di, es

            mov si, 0

            call show_str  ;显示一行内容

            inc dh

            add bx, 4

            add bp, 2

            pop cx

            dec cx

            cmp cx, 0

            jne top0

            je toend

      top0: jmp far ptr p0

            

     toend: mov ax, 4c00H

            int 21H



  ;子程序(用来在屏幕指定位置显示内容的子程序, 内容默认放在ds段中)

  ;  参数:dh-显示的行数, dl-显示的列数, cl-属性字节, di-内容所在的段, si-移量地址

  ;  返回:无

  show_str: push ds

            push es

            push ax

            push bx  

            push dx  ;以上保存子程序中要用到的寄存器

            mov ds, di

            mov ax, 0B800h  ;显存首地址

            mov es, ax

            mov al, 160  ;显存中每行所占的字节数(每行能显示80个字符)

            mul dh

            mov bx, ax

            mov al, 2  ;显存中每个显示字符所占的字节数(显示字符=属性字节+ASCII码)

            mul dl

            add bx, ax  ;此时bx为由参数指定显示位在显存中的首地址

            mov ch, 0

            mov dl, cl  ;因为要用cx来检测是否处理到字符串的结尾0, 先用dl保存参数cl

        s0: mov cl, ds:[si]  ;取出之前处理好的一个字符

            jcxz sok

            mov byte ptr es:[bx], cl  ;往显存中存入ASCII码

            mov byte ptr es:[bx].1h, dl  ;往显存中存入属性字节

            inc si  ;移动到下一个字符

            add bx, 2  ;移动到下一个显存字符空间的首地址

            jmp s0

       sok: pop dx

            pop bx

            pop ax

            pop es

            pop ds

            ret


      ;子程序(用来转成十进制数对应的ASCII码的子程序)

      ;  参数:ax-保存数值的低16位, dx-保存数值的高16位

      ;  返回:si-保存十进制ASCII码的首地址, di-保存段地址

      dtoc: push ds

            push bx

            push cx

            mov cx, mathsg

            mov ds, cx

            mov di, cx

            mov si, 0Eh  ;初始化si指向mathsg段中倒数第二个字节空间

        d0: mov cx, 0Ah  ;cx保存除数

            call divdw

            add cl, 30h  ;由于除数是10 所以结果中的余数一定小于10,取cl就行了

            mov byte ptr [si], cl  ;保存对应的十进制数的ASCII值

            call zerodw

            jcxz dok

            dec si  

            jmp d0

       dok: pop cx

            pop bx

            pop ds 

            ret


     ;子程序(进行不产生溢出的除法运算)

     ;  参数:dx为被除数的高位字,ax为被除数的低位字,cx为除数占一个字空间

     ;  返回:dx保存商的高位字,ax保存商的低位字,cx保存余数点一个字空间

     divdw: push bx ;下面要用bx来保存第一次除法结果中的商,先入栈保存下之前的信息,以免冲突

            push ax ; ax现在存有参数,但要用到ax参与除法运算,所以也先入栈保存份

            mov ax, dx

            mov dx, 0

            div cx  ; 执行分解后的第一次除法: H/n

            mov bx, ax  ; bx保存第一次除法结果中的商

            pop ax  ; 将入栈保存的ax参数值出栈,此时dx的值为第一次除法结果中的余数

            div cx  ; 执行第二次除法: [rem(H/n)*65536+L]/n

            mov cx, dx  ; 根据题目要求,将除法结果中的余数用cx保存

            mov dx, bx  ; 根据题目要求,将除法结果中的高位字用dx保存

            pop bx  ; 还原bx的值,避免子程序之外也用到了bx而产生寄存器冲突

            ret 


     ;子程序(判断32位的数是否为0)

     ;  参数:dx为被除数的高位字,ax为被除数的低位字

     ;  返回:cx 当dx、ax都为0时才为0

     zerodw: cmp dx, 0

             jne nz

             cmp ax, 0

             jne nz

             mov cx, 0

             jmp zok

         nz: mov cx, 1

        zok: ret


 codesg ends


end start

:<----------------------------------------------------------------------------------------


运行结果:

技术分享


总结:

    调试了一个晚上,终于弄出来了,很激动,又进一小步。调试时又出现了死循环,由于对栈的操作不当引起的,下次一定要注意入栈与出栈要配对,并且出栈顺序与入栈顺序相反


-------------   以上的习题部分及代码引用于王爽老师的<<汇编语言>>第二版  ----------------


本文出自 “9256624” 博客,请务必保留此出处http://9266624.blog.51cto.com/9256624/1617775

学习<<汇编语言 -王爽>>,自已完成的一道课程设计题 (5)

标签:汇编   汇编语言   

原文地址:http://9266624.blog.51cto.com/9256624/1617775

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!