cc20911 发表于 2022-9-3 13:27:06

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

本帖最后由 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,
      MOV ES:,AX
      MOV AX,
      MOV ES:,AX
      
      ;年收入
      MOV AX,
      MOV DX,

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

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

      
      ;平均收入
      MOV AX, ;被除数的低位
      MOV DX, ;被除数的高位
      MOV CX, ;CX=除数
      CALL divdw

      MOV DI,36;表格第一行的“平均”从偏移36开始
      ;MOV ES:,AX;商的低位
      ;MOV ES:,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, ;判断字符是否为0
      JCXZ str_ok;为0代表已到字符串尾,退出

      MOV AL,CL ;字符存入低位,与显存对应      
      MOV ES:,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:,AL
      INC SI
      LOOP s_dc3
         
dtoc_ok:
      POP SI
      POP AX
      POP BX
      POP CX
      POP DX            
      ret

code ends
end start
页: [1]
查看完整版本: 汇编语言第4版(王爽)_课程设计1_p211页