鱼C论坛

 找回密码
 立即注册
查看: 1285|回复: 0

[汇编作业] 汇编语言第4版(王爽)_课程设计1_p211页

[复制链接]
发表于 2022-9-3 13:27:06 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 cc20911 于 2022-9-3 13:48 编辑

在XP虚拟机里面编译链接没问题,运行也没问题,就是显示不出来,忙活了半天了,还是找不到问题在哪里,麻烦有空的大佬帮我看看,非常感谢

assume CS:code

datasg segment
  ;表示21个年份的21个8位型数据
  DB '1975','1976','1977','1978','1979','1980','1981','1982'
  DB '1983','1984','1985','1986','1987','1988','1989','1990'
  DB '1991','1992','1993','1994','1995'
  ;表示21年中每年公司总收入的21个32位型数据   32位的被除数
  DD 16,22,383,1356,2390,8000,16000,24486,50065,97479,140417
  DD 197514,345980,590827,803530,118300,1843000,2759000
  DD 3753000,4649000,5937000
  ;21年当中每年公司的的雇员数量,16位    16位的除数
  DW 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037
  DW 5635,8226,11542,14430,15257,17800
datasg ends

tabll segment
  DB 21 dup('year      summ            ne        ???  ',0)
tabll ends

stack segment
  Dw 32 dup(0)
stack ends


code segment
start:
        MOV AX,datasg
        MOV DS,AX
        MOV AX,tabll
        MOV ES,AX
        MOV AX,stack
        MOV SS,AX
        MOV sp,64

        MOV BX,0
        MOV SI,0
        MOV DI,0
        MOV CX,21
   s1:
  ;======把数据先放入表格中,等待打印===============
        PUSH CX
        
        ;年份   
        MOV AX,[BX]
        MOV ES:[DI],AX
        MOV AX,[BX+2]
        MOV ES:[DI+2],AX
      
        ;年收入
        MOV AX,[BX+54h]
        MOV DX,[BX+56h]

        MOV DI,10  ;表格第一行的“收入”从偏移10开始            
        CALL dtocdd ;dtocdd的目标为es:di
            
        ;人数
        MOV AX,[SI+0a8h]
        MOV DX,0 ;人数只有16位,没有高位

        MOV DI,26  ;表格第一行的“收入”从偏移26开始            
        CALL dtocdd ;dtocdd的目标为es:di

      
        ;平均收入
        MOV AX,[BX+54h] ;被除数的低位
        MOV DX,[BX+56h] ;被除数的高位
        MOV CX,[SI+0a8h] ;CX=除数
        CALL divdw

        MOV DI,36  ;表格第一行的“平均”从偏移36开始  
        ;MOV ES:[DI+0dh],AX  ;商的低位
        ;MOV ES:[DI+0fh],DX  ;商的高位      
        CALL dtocdd
            
        ;
        ADD BX,4h ;控制年份和收入,都是4字节型
        ADD SI,2h ;控制人数,2字节型
        ADD DI,2Ah ;控制表格行数,+41等于换行

        POP CX
        LOOP s1

   s2:
        ;在屏幕上打印除表格数据
        MOV DH,1  ;屏幕第1行开始
        MOV DL,3  ;屏幕第3列开始
        MOV CL,2  ;绿色

        PUSH DS
        MOV AX,DS
        MOV ES,AX
        MOV SI,0
        CALL show_str ;show_str使用的参数为ds:si,
                      ;这里要打印的是ES:DI
        POP DS

        MOV AX,4C00H
        INT 21H
  ;====================================================

divdw:  
        ;参数:AX=被除数低16位,DX=被除数高16位
        ;CX = 除数
        ;返回值:AX=结果的低16位,DX=结果的高16位      
        ;CX = 余数
        ;原理:汇编语言(王爽)实验10.2
        
        ;做高位的除法
        PUSH AX    ;低16位先保存

        ;高16位先做除法
        MOV AX,DX  ;AX这时是高16位
        MOV DX,0   ;dx置0为了不影响余数位
        DIV CX     ;相当于原被除数的高位先做除法
        MOV BX,AX  ;AX=商,暂时用bx保存,余数在DX中

        ;低16位再做除法
        POP AX     ;取低16位,dx现在是高位除法的余数
        DIV CX     ;继续除法,除完之后AX保存商

        MOV CX,DX   ;第二次除法的余数放入cx
        MOV DX,BX   ;第一次除法的商为整体除法的高位
        ;此时整体除法的商分别放在DX(高16位),AX(低16位)中
        ret
        


show_str:
        ;参数:dh=行号(0-24),dl=列号(0-79)
         ;cl=颜色,ds:si指向字符串首地址
        PUSH AX
        PUSH BX
        PUSH CX
        PUSH DX
        PUSH SI
        PUSH DI
        
        ;定位行========================
        MOV Al,0a0h ;每行偏移0a0h,160个字节
        DEC DH   ;第N行开始,所以偏移N-1行,8位乘以8位,
        MUL DH   ;结果存放在16位ax中
                 
        MOV BX,AX ;定位好的 “行” 位置偏移放BX中
        ;=============================
        
        ;定位列=======================
        MOV AL,2   ;每列偏移2个字节
        MUL DL   
        SUB AX,2  ;第N列开始,所以偏移N-1列

        ADD BX,AX  ;此时BX存放行与列的偏移地址
        ;=============================

        ;目标区域->显存===============
        MOV AX,0b800h ;显存开始的地址
        MOV ES,AX
        MOV DI,0  ;di指向显存的偏移地址   
        ;=============================

        ;把数据放入显存区域 ==========
        MOV AH,CL   ;颜色存入高位
        MOV CH,0   ;下面需要用到CL,先把CH置0         
    s:  
        MOV CL,[SI] ;判断字符是否为0
        JCXZ str_ok  ;为0代表已到字符串尾,退出

        MOV AL,CL ;字符存入低位,与显存对应        
        MOV ES:[BX+DI],AX  ;AL=字符,AH=颜色

        INC SI
        ADD DI,2  ;显存一个字符占2字节
        JMP short s
        ;==============================
  str_ok:
        POP DI
        POP SI
        POP DX
        POP CX
        POP BX
        POP AX
        RET



dtocdd:
        ;将word型整数转换为ASCII码字符串并保存
        ;参数:AX=数据低16位,DX=高16位
        ;es:di指向字符串首地址
        PUSH DX
        PUSH CX
        PUSH BX
        PUSH AX
        PUSH SI

        MOV BX,0 ;BX在子程序中用来存放位数,
                 ;用栈来临时存放修改后的字符

  s_dc1:
        MOV CX,10 ;cx = 除数
        
        CALL divdw

        ADD CX,30h
        PUSH CX ;保存转换号的字符

        ;为什么要给CX之后再OR,是为了保留AX,DX的        
        ;值,不破坏下一次除法的参数      
        MOV CX,AX  ; 低位商给CX
        OR CX,DX ;高位与低位只要任意不为0,证明商不为0,
                ;还要继续除法
        JCXZ s_dc2

        INC BX  ;bx保存有几位数,发现一位就加1

        JMP short s_dc1

  s_dc2:
        ADD CX,30h
        PUSH CX

        INC BX  ;再进行一次栈操作
                ;补充当商为0而余数不为0时的情况

        MOV CX,BX ;总共有几位数,就循环几次
        MOV DI,0

  s_dc3:
        POP AX
        MOV ES:[DI],AL
        INC SI
        LOOP s_dc3
         
  dtoc_ok:
        POP SI
        POP AX
        POP BX
        POP CX
        POP DX            
        ret

code ends
end start
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-28 07:38

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表