;第171实验7:题之意为要把归类给出的数据重新编成一个较好看的表格。
assume  cs:code,ds:data1,ds:data2,ds:data3
data1  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'
data1  ends
;21个年份●属字符串
data2  segment
dd   16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd   345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
data2  ends
;21年公司总收入●属双字型数据
data3  segment
dw  3, ,7, ,9, ,13, ,28, ,38, ,130, ,220, ,476, ,778, ,1001, ,1442, ,2258, ,2793, ,4037, ,5635, ,8226, ,11542, ,14430, ,15257, ,17800
data3  ends;未编start:部分先masm并d ss:0可预先在debug中看到这些数据。
;21年顾员人数变化●属字型数据


table  segment
db  4210h  dup(0);●●●●●●●为了显示,此区要设得足够大,将原杂数清0,否则会读到不正确数,导致div出问题●●●●●●●●
table  ends

code  segment
start:
mov  ax,table
mov  es,ax;通知地址
mov  cx,21;●如果下面能搞好每年一行,那么cx=21就可以。
mov  bx,0
mov  si,0
mov  bp,0

s21:
mov  ax,data1
mov  ds,ax;通知地址,年份占有数据区
push  cx
mov  cx,4
;mov  di,0;●di是个不能乱用的东西!用上它后年份搬到es中竟全变成1111,妈的!
 s1:mov  al,ds:[si];读入不必bx(在前面的认识si例子中,si每次读一个字(定义为数字时),这次只读一个字节(定义为字符串时))
mov  es:[bx],al;写入要用bx
inc   bx
inc   si
loop  s1;完成年份填表。


mov  ax,data2
mov  ds,ax;通知地址,收入占有数据区


mov  ax,ds:[bp];读收入,收入是双字,读法须有讲究吗?试把197514(=3038A=13DE:0000 8A 03 03 00)放在第一个,
mov  dx,ds:[bp+2]
;●●●●●●与下面那个bp不同步,需修改
mov  es:[bx+11],ax;填收入
mov  es:[bx+13],dx
push  ax;保护此数用于下面的除法运算

mov  ax,data3
mov  ds,ax;通知地址,人数占有数据区
mov  ax,ds:[bp];读人数
add   bp,4;这个改为+4后,收入填入正确了,为了让人数与此同步,在人数原始数据区每个数据间放个空格或0,问题应可园满解决了。
mov  es:[bx+26],ax;填人数,根据debug  d es:0确认bx+6
;上面三项成功完成。

;最后一项求人平均收入(●取整):须完全熟记168页故有规定才能搞好下面各项的关系(现未搞清,刚从除法那边抄来这段)已搞清楚。
pop  ax
div    word  ptr  es:[bx+26];●指明除数的位置及类型。

mov  es:[bx+39],ax;填人平均收入

add  bx,172;bx负责控制行,加12后第二次s21循环会从es:0的第二行写起。

pop  cx;●有无设置栈及有无栈指针似乎关系不大,重要的是这两句顺序搞反cx和di的值便搞反!!!!
loop  s21






;●●●●●●想先在此把年份后的三组数据读出来,转成字符后存在原数字后面
mov  bx,0
mov cx,21

aa:mov  si,0
push  cx;●●●●●●●●●●●●●●●●可能是这句放在aa:上面(即放在循环外)引起的?是!!!!!!!!!!!!
mov  ax,es:[bx+15];读收入,收入是双字,读法须有讲究吗?试把197514(=3038A=13DE:0000 8A 03 03 00)放在第一个,
mov  dx,es:[bx+17];●怪,写入时明明是es:[11]处,实际处于es:[15]处
add  si,18
call  divdw
;●●●●●●发现debug有不稳定,昨晚转好1976年收入,到此要继续时两三次都自动跳出运行,今天却不会●●
;会不会是昨运行太久太热引起?
;●●●●跟踪显示1975直到1989收入803530写入没错,但1990的1183000却写11830,少了两个0,●所以divdw子程序还要修改:
;16000正常写入,因它是用第一部分处理的;1183000则分两部分处理,故第一部分的ax=0,及dx=0时不许结束●●●●●●
;但如此一来第一部分遇到全0时如何跳出循环?●●●●跟踪显示修改后最后一个收入也正确写入●●●●●●
;但运行却产生除法溢出提示,为什么?!!!!!!!!loop最后pop时发现cx=17ee,可见是cx发生错误,故在pop前加cx=0
;还是不行,还是cx=17ee.debug t=0  850到达1993年写收入处,用t继续.●改push cx位置后运行没再发出溢出警告
;若loop进入不断循环,则divdw子程序会读到0导致错误。
;●●●●●●●●●●●●●●●●此段完成收入转字符工作●●●●●●●●●●●●●●●●●●●●●●●●●●●●


mov  dx,0
mov  ax,es:[bx+30];读人数
mov  si,30
call  divdw;此段完成人数转字符工作●●●●●















add  bx,176
pop  cx
loop  aa

;显示(因这里要单独占用一ds,所以不能在上面一边计算一边显示)
mov  ax,0b800h
mov  ds,ax;通知显存地址




mov  bx,0
mov  cx,21
kk:mov  ax,0;不清0则al多读出数值.
mov  al,es:[bx];读出
mov  ds:[bx],al;写入显存区
mov byte ptr ds:[bx+1],02

mov  al,es:[bx+1];读出
mov  ds:[bx+2],al;写入显存区
mov byte ptr ds:[bx+3],02

mov  al,es:[bx+2];读出
mov  ds:[bx+4],al;写入显存区
mov byte ptr ds:[bx+5],02


mov  al,es:[bx+3];读出
mov  ds:[bx+6],al;写入显存区
mov byte ptr ds:[bx+7],02;●●●完成年份读写


;●●●●原来还有个错误,下面这些是数字,还没有调用前面设计的转换程序!!!!!!
mov  ax,0
mov  al,es:[bx+6];读收入
mov  ds:[bx+20],al;写收入到显存区
mov byte ptr ds:[bx+21],02

mov  al,es:[bx+8];第二位
mov  ds:[bx+22],al
mov byte ptr ds:[bx+23],02

mov  al,es:[bx+10];第三位
mov  ds:[bx+24],al
mov byte ptr ds:[bx+25],02;●有个问题:前面那些数位数较少,没读到数会出现什么情况?●

mov  al,es:[bx+12];第四位
mov  ds:[bx+26],al
mov byte ptr ds:[bx+27],02

mov  al,es:[bx+14];第五位
mov  ds:[bx+28],al
mov byte ptr ds:[bx+29],02

mov  al,es:[bx+16];第六位
mov  ds:[bx+30],al
mov byte ptr ds:[bx+31],02

mov  al,es:[bx+18];第七位
mov  ds:[bx+32],al
;mov byte ptr ds:[bx+33],02;●怪,多此句就汇编失败?!第七位已读出显示白色,难道此位不能改颜色?
;●●●●想先完成年份和收入显示,成功后再增加后两项。●●●●●●●●●●●●





;mov  ax,0;●●●●●●●●●●●●怪事!在此增加任何语句都导致汇编失败!!!!是否程序太长越段须far属性?●●●●
;mov  al,es:[bx+22];读人数,;用debug u全部列出都在一个段中,那什么原因?
;mov  ds:[bx+40],al;写人数到显存区
;mov byte ptr ds:[bx+41],02

;mov  al,es:[bx+24];第二位
;mov  ds:[bx+42],al
;mov byte ptr ds:[bx+43],02

;mov  al,es:[bx+26];第三位
;mov  ds:[bx+44],al
;mov byte ptr ds:[bx+45],02

;mov  al,es:[bx+28];第四位
;mov  ds:[bx+46],al
;mov byte ptr ds:[bx+47],02

;mov  al,es:[bx+30];第五位
;mov  ds:[bx+48],al
;mov byte ptr ds:[bx+49],02;●●发现此段搬到“call  divdw;此段完成人数转字符工作●●●●●”下汇编就可以,见鬼,不知原因!
;难道与选ds做显存有关?

























add  bx,320;●●●●由160改为360后显出1995  5937000●可见须占领整个屏幕才能正常显示●●●●●●●●●●●●
loop  kk

mov  ax,4c00h
int  21h

;除法不溢出程序数字转显示字符字程序
divdw  proc
mov  cx,0ah;这个数是上面公式中的N
mov  di,1000;●●要么写10进制mov  bx,1000,要么写16进制mov  bx,03e8h重点在于h●●
mov  bp,0                                                ;●●跟踪显示上句处于t=0  380位置
cmp  dx,0;先看看,若dx=0,则要处理的是小于65536
je  qq;小于65536就跳过/1000的处理

div di
;得ax=12345,dx=666,即将12345666/1000分两部分处理
push ax
mov  ax,dx
yy:mov  ax,ax
mov  dx,0
div  cx;ax=66,dx=6
add  dx,30h
mov  es:[si+bx],dx;写到数据区,从右向左写
sub  si,2
inc  bp
cmp  bp,3;不用ax=0作判断,而用是否已写了3次(无论是否是0)作判断!
je   xx  ;●遇到全0时如何跳出循环?写3个0就跳出写3个0就跳出
jmp  yy
;处理12345
xx:pop ax
qq:mov  ax,ax
mov  dx,0
div  cx;ax=66,dx=6
add  dx,30h
mov  es:[si+bx],dx;写到数据区,从右向左写
sub  si,2
cmp  ax,0
je  qqq
jmp  qq
qqq:
ret
divdw  endp

code  ends
end  start