汇编语言_课程设计1
【交流学习,共同进步】【大家新年快乐啊!!!恭喜发财,红包拿来!!!!】
下面这个代码我敲了4个小时,头都大了,终于搞定了,不过还是存在很多可以优化的地方,有想法的小伙伴可以试试把我的代码优化一下哦!
还是那句话,我暂时没看小甲鱼老师的答案讲解。因为,只有不看答案,我的结题思路才会是全部原创的,哈哈哈哈。这样做出来的代码,才有更大的交流学习的价值。
assume cs:code, ss:stack
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'
;以上是表示21年的21个字符串,一共84个字节
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
;以上是表示21年公司总收入的21个dword型的数据,一共84个字节
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
;以上是表示21年公司雇员人数的21个word型的数据,一共42个字节
datasg ends
data segment ;数据段默认用0结尾
dw 24 dup(0)
data ends
stack segment ;我用了较多的栈空间,怕溢出,自己定义了一个栈
dw 32 dup(0)
stack ends
code segment
start: mov ax,stack ;初始化栈段
mov ss,ax
mov sp,32
mov ax,data ;初始化数据段
mov ds,ax
mov ax,datasg ;初始化待转化的数据段
mov es,ax
mov si,0 ;si记录数据段记录的位置,永远指向结尾的0
mov di,0 ;di记录待转化数据段的当前转化位置,低指向下一个待转化的地址,0是年份的开始,84是是总收入的起始,168是雇员人数的起始
mov dh,2 ;提前定dh行数
push es ;置零原先显存上第一页的数据,每一页显存4000个字节,从d8000h开始
mov ax,0b800h
mov es,ax
mov ax,0
mov cx,2000
clear_gpu:
mov es:,ax
add di,2;
loop clear_gpu
pop es
mov di,0
mov cx,21
dfg:
push cx
push dx
mov si,0
mov ax,es: ;年份转入数据段
mov ds:,ax
mov ax,es:
mov ds:,ax
mov ax,es:
mov ds:,ax
mov ax,es:
mov ds:,ax
mov ax,0 ;向字符串填入0结尾
mov ds:,ax
mov si,0 ;输出年份
pop dx
mov dl,12
mov cl,2
call show_str
push dx
mov ax,es: ;总收入转化成acsell码转入数据段
mov dx,es:
mov si,12 ;si指向总收入开始的地址,使其为12
call dtoc_plus ;将ax和dx中的doubleword数据,变成字符串,记录在当前ds:【si】的位置,记录完成后si指向字符串末尾的0
mov si,12 ;输出公司总收入
pop dx
mov dl,24
mov cl,2
call show_str
push dx
mov si,24 ;si指向总雇员开始的地址,使其为24
push di ;di入栈保存,cx入栈保存
push cx
mov ax,di ;使di=二分之一的di
mov cx,2
mov dx,0
div word ptr cx
mov di,ax
mov bp,ax ;额外用bp存放二分之一的di
mov ax,es: ;总雇员转化成acsell码转入数据段
mov dx,0
call dtoc_plus ;将ax和dx中的doubleword数据,变成字符串,记录在当前ds:【si】的位置,记录完成后si指向字符串末尾的0
pop cx ;还原cx与di
pop di
mov si,24 ;输出雇员人数
pop dx
mov dl,36
mov cl,2
call show_str
push dx
mov ax,es: ;计算人均收入的总收入
mov dx,es:
mov cx,es:
div word ptr cx
mov dx,0
mov si,36 ;si指向人均收入开始的地址,使其为12
call dtoc_plus ;将ax和dx中的doubleword数据,变成字符串,记录在当前ds:【si】的位置,记录完成后si指向字符串末尾的0
mov si,36 ;输出人均收入
pop dx
mov dl,48
mov cl,2
call show_str
add di,4
add dh,1
pop cx
dec cx
jcxz yui
jmp dfg
yui:mov ax,4c00h
int 21h
;将ax和dx中的doubleword数据用字符串的acsll码,记录在当前ds:【si】的位置,用0做结束,结束时si指向0所在位置
dtoc_plus:
push dx ;保留原函数的值
push cx
push ax
push bx
mov bx,0 ;先入栈一个0作为字符串的结尾
push bx
in_stack: ;处理dword数据的acsll值,并存入栈中
mov cx,10
call divdw ;dx被除数高16位,ax被除数低16位,cx除数,商的高16位在dx,低16位在ax,余数给cx
add cx,30h ;acsll码值入栈
push cx
mov cx,dx ;双重检查,只有当ax和dx都是0才会通过
inc cx
loop in_stack
mov cx,ax
inc cx
loop in_stack
out_stack:
pop ax ;栈里面是按word型存储的,但是,因为存进去的数不可能超过8位,所以只有low位有值,取al即可
mov ds:,al
inc si
mov cx,ax
inc cx
loop out_stack
dec si ;si回去一位,指向0
pop bx
pop ax
pop cx
pop dx
ret
;dx被除数高16位,ax被除数低16位,cx除数,结果的高16位给dx,低16位给ax,余数给cx
divdw:
push bx ;保存可能变动的值
push ax
mov ax, dx ;高16位
mov dx, 0 ; (新组合的32位的被除数)=0000 000fh
div cx ;此时(dx)=余数 和 低16位 组合成一个新的32位的被除数
mov bx, ax ;结果的高16位
pop ax ;低16位
div cx
mov cx, dx ;余数
mov dx, bx ;结果的高16位
pop bx
ret
;将dh看作行号(0-24),dl看作列号(0-79),cl看作颜色,
;ds:si指向字符串首地址,0为结束的字符串,放入显存指定位置,结束时si指向0所在位置
show_str:
push ax ;因为不知道主函数是否用了ax,先进栈保存,后续会使用ax寄存器
push di ;因为不知道主函数是否用了di,先进栈保存,后续会使用di寄存器
push es ;因为不知道主函数是否用了es,先进栈保存,后续会使用es寄存器
push cx ;后面会对cx改动
push dx
mov ax,0b800h ;显存起始地址给es,用di记录位置
mov es,ax
mov di,0
mov al,160 ;每行160个字节,每个字符2个字节,计算字节位置后,给di寄存器
mul dh
mov dh,0
add ax,dx
add ax,dx
mov di,ax
mov al,cl ;写入字符串
mov ch,0
read_in:
mov cl,ds:
jcxz ok
mov es:,cl
mov es:,al
add di,2
inc si
jmp short read_in
ok: pop dx
pop cx
pop es
pop di
pop ax
ret
code ends
end start
还是发不了图,积分不够,不过我运行过了,是对的哦!
累了,累了,大家加油,好好学习,如果可以的话,帮我刷刷回帖,多顶顶,爱你们哦!{:10_264:}
收藏了{:5_106:}
页:
[1]