【王爽汇编】课程设计1,源码及详细分析。
本来也没认为自己能写出来的,好多次想放弃的,可能心里有点不甘心吧,昨天晚上开始写,今天白天花了一天时间在公司研究,主要是前面卡在那个 取余数地方,现在写了出来,也是想分享一下我的心情,我觉得呢,这代码啊,还是别一次性想完,因为你也想不完,刚开始的时候,我也一点头绪都没有,然后我想,那就先把年份输出来吧,这个我肯定会做啊,然后当我写了一点的时候我发现,那个收入我应该也能输出来啊,然后就一点一点的写玩了,虽然会出现很多错误,但是我挺享受这种过程的,感觉反正就是一个值爽。
下面我就来讲一下我分析这个程序的思路吧:
1.我先开辟一段空间,来保存 所有转换后的 年份,收入,人数,平均工资
2.将所有的数据写入到显存
3.年份这个很好办,本身就是ascii码数据,直接写入就行了
4.收入,这个需要写一个取余数的方法就行了,主要是要知道怎样让数据的顺序不变,因为取余数是从低到高(这里代码里面有相信分析)
5.人数和和上面一样。平均工资,也就多了一个 除法的方法。
下面是代码,我也就不隐藏了,没必要,不过我希望各位朋友都能把自己的思路分享一下,大家一起进步。
assume ds:data,cs:code,SS:stack,ES:table
data 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,690827,803530,1183000,1843000,2759000,3753000,4649000,593700
;人数
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,45257,17800
data ends
;栈
stack segment
Db 160 dup(0)
stack ends
;保存年份 收入 人数 平均工资 ,里面的空格我写了40个,这里面都是保存转换成ascii码后的数据
table segment
DB 21 dup(' ')
table ends
code segment
start:
MOV AX,data
MOV DS,AX
MOV AX,table
MOV ES,AX
MOV AX,stack
MOV SS,AX
MOV sp,160
MOV CX,21
MOV bx,0 ;索引年份和收入,每一个数据都是4个字节
MOV SI,0 ;索引目标空间
MOV DI,0 ;索引人数,每一个数据都是2个字节
S:
CALL chuansong ;写入年份
;写入收入
MOV AX,84 ;收入的低16位
MOV DX,84 ;收入的高16位
PUSH si
add SI,8 ;从偏移地址为8的空间开始写入
CALL xssr
POP SI
;下面的写入人数,和计算平均工资,简单看看就能看懂,都是调用一个方法
;写入人数
MOV AX,DS:168
MOV DX,0
PUSH SI
add SI,18
CALL xssr
POP SI
;写入平均工资
PUSH CX
MOV AX,84
MOV DX,84
MOV CX,DS:168
CALL chufa ;计算平均工资
POP cx
; 这里又和上面一样了
PUSH si
add SI,30
CALL xssr
POP SI
ADD DI,2
ADD bx,4
ADD SI,40
LOOP S
; 这下面就是 输出了很简单,我就不解释了,好累。
MOV AX,0b800h
MOV ES,AX
MOV AX,table
MOV DS,AX
MOV DI,0
MOV bx,0
MOV CX,21
s4:
PUSH CX
PUSH di
MOV CX,40
s5:
MOV AL,
MOV ES:,AL
MOV BYTE ptr ES:,7
ADD DI,2
INC bx
LOOP s5
POP DI
POP cx
ADD DI,160
LOOP s4
MOV AX,4c00h
INT 21h
;因为年份本身就是以ascii码存放的,所以就不要转换,直接写到目标空间就行了
chuansong:
PUSH CX
PUSH SI
PUSH bx
PUSH ax
MOV CX,4
NF:
MOV AL,
MOV ES:,AL
INC si
INC bx
LOOP NF
POP ax
POP bx
POP si
POP CX
RET
;16位除法
;参数,(被除数)高位dx,低位cx,除数cx
;返回值,高位dx,低位cx,余数cx
chufa:
PUSH bx
MOV bx,AX ;先保存低16位
MOV AX,DX ;先计算高16位,将高16位给ax
MOV DX,0 ;为了不影响 16 位除法运算 所以我清空dx ,这里不明白的可以百度 一下 div 16运算
DIV CX
PUSH AX ;保存高位
MOV AX,bx ;bx 先前保存的是低16位 ,现在还原继续球低16位运算
DIV CX
MOV CX,DX ;将余数给cx,ax存商的低16位,dx存高16位
POP DX
POP bx
RET
;
xssr:
PUSH CX
PUSH SI
PUSH DI
;di是用来记录 当前 数据的 位数假如数据是1234那di就是=4,
;这个di我用来将数据倒置,因为取余数,后的数据就变成 4321 了,数据就不对,
;所以我每次取一个余数就push 一次,然后记录次数,最后就pop出去,这样就能使数据不会倒过来
MOV DI,0
H:
MOV CX,10 ; 10进制除以10 取余数
CALL chufa ;取出余数,余数是放在cx里面,其实是在cl里面
ADD CL,30h ;将余数转换为ascii码, +30H,这里不明白为什么是加30H ,自己去对照ascii码表
MOV CH,0 ;现在开始将每一次的余数压栈, 因为栈运算是操作2个字节,所以我用将ch置0,cl本身就是存放的余数。
PUSH CX
INC DI ;每一次入栈记录 次数
MOV CX,DX ;判断商是否为0 ,为零就不要在取余数了, dx存放高位商,前面解释过了
JCXZ pdax ;如果高位商为零, 说明 整个商 可能为零, 不过高位商不为零,那低位商也就不需要判断了,,说实话真麻烦
JMP H
pdax:
MOV CX,AX ;判断 低位商是否为0
JCXZ OK ;如果这里被执行,说明 整个商为零,然后就开始pop了,真正的写入数据到目标空间
JMP H
OK:
MOV CX,DI ;di 为余数的个数,也就代表push了几次,所以我们就要循环pop几次
zha:
POP AX ;将余数出栈
MOV ES:,AL;前面入栈的时候cl 为余数,ch为0, 所有al 对应 cl
INC SI
LOOP zha
POP DI
POP si
POP CX
ret
code ends
end start
我也要自己写一个:mad::mad::mad::mad: 我自己也去写一个看看呀。哈哈。:lol: 我以前用了一个星期写………… 我也是刚写出来,共同进步 15岁的小朋友 发表于 2014-5-23 08:08 static/image/common/back.gif
我以前用了一个星期写…………
第一次写,用了五天 decoder 发表于 2014-5-24 20:18
第一次写,用了五天
我五天在学校写代码 1天在家调试 第七天成功了! 15岁的小朋友 发表于 2014-5-24 20:31 static/image/common/back.gif
我五天在学校写代码 1天在家调试 第七天成功了!
:handshake牛,我刚刚写完,大脑已经不听使唤了 decoder 发表于 2014-5-24 20:33
牛,我刚刚写完,大脑已经不听使唤了
累了 就早点睡罗我刚写完也是这样 本帖最后由 kikiatw 于 2014-6-4 23:38 编辑
寫好久的...
ASSUME CS:CODE, DS:DATA, SS:STACK
DATA SEGMENT
DB '1975','1976','1977','1978','1979','1980','1981' ;0
DB '1982','1983','1984','1985','1986','1987','1988'
DB '1989','1990','1991','1992','1993','1994','1995'
DD 16,22,382,1356,2390,8000,16000,24486 ;84
DD 50065,97479,140417,197514,345980,590827,803530
DD 1183000,1843000,2759000,3753000,4649000,5937000
DW 3,7,9,13,28,38,130 ;168
DW 220,476,778,1001,1442,2258,2793
DW 4037,5635,8226,11542,14430,15257,17800
DATA ENDS
TABLE SEGMENT
DB 21 DUP ('YYYY EARN EP AV ')
TABLE ENDS
STACK SEGMENT
DW 50H DUP (0)
STACK ENDS
CODE SEGMENT
MAIN:
MOV AX,STACK ;initial stack segment
MOV SS,AX
MOV SP,50H
MOV AX,DATA ;initial data into table segment
MOV DS,AX
MOV AX,TABLE
MOV ES,AX
CALL SORT
MOV AX,TABLE ;initial print data
MOV DS,AX
MOV AX,0B800H
MOV ES,AX
MOV BX,0
MOV SI,0
MOV DI,0
MOV CX,21
M1: PUSH CX
MOV AX,[SI] ;print character
MOV ES:[DI],AL
MOV ES:[DI+2],AH
MOV AX,[SI+2]
MOV ES:[DI+4],AL
MOV ES:[DI+6],AH
MOV AX,[SI+7] ;print DEC number to string
MOV DX,[SI+5]
MOV CX,DI
ADD CX,20H
CALL DTOC32
MOV AX,0 ;print DEC number to string
MOV DX,[SI+10]
MOV CX,DI
ADD CX,40H
CALL DTOC32
MOV AX,0 ;print DEC number to string
MOV DX,[SI+13]
MOV CX,DI
ADD CX,60H
CALL DTOC32
ADD SI,10H
ADD DI,0A0H
POP CX
LOOP M1
MOV AX, 4C00H
INT 21H
SORT: MOV CX,21
MOV BX,0
MOV SI,0
MOV DI,0
S1: PUSH CX
MOV AX,[SI]
MOV ES:[DI],AX
MOV AX,[SI+2]
MOV ES:[DI+2],AX
MOV AX,84[SI]
MOV ES:[DI+5],AX
MOV DX,86[SI]
MOV ES:[DI+7],DX
MOV CX,168[BX]
MOV ES:[DI+10],CX
DIV CX
MOV ES:[DI+13],AX
ADD DI,10H
ADD SI,04H
ADD BX,02H
POP CX
LOOP S1
RET
;DTOC32 show the double word DEC on the screen
;AX:H word
;DX:L word
;CX:Location offset at B800H Segment
DTOC32: PUSH DI
PUSH SI
MOV DI,CX ;DI location pointer
MOV SI,DX ;SI to save low word
MOV BX,0 ;BX to be byte count
DT1: MOV DX,0
MOV CX,10
DIV CX
MOV CX,AX
MOV AX,SI
MOV SI,CX
MOV CX,10
DIV CX
PUSH DX
INC BX
MOV CX,AX
JCXZ DT2
MOV AX,SI
MOV SI,CX
JMP DT1
DT2: MOV CX,BX
DT3: POP DX
ADD DL,30H
MOV ES:[DI],DL
ADD DI,2
LOOP DT3
POP SI
POP DI
RET
CODE ENDS
END MAIN
樓主請問一下您代碼是怎麼貼的? 学习下!!! {:1_1:}:sad:big:cry:shy::ton::shock:学习下!!! kikiatw 发表于 2014-6-4 23:32
樓主請問一下您代碼是怎麼貼的?
在发表工具档时有<>,点这个,再贴上去。 我用了两种方法,一种和楼主一样,先开一段空间存转成字符以0为间隔,然后再存入显存;另一种是字符转化和存入显存同时进行,不用空间先储存转化好的字符,一步到位。
页:
[1]