|
主题 : : 我的子程序代码,大家也贴出自己的相互学习吧? [待解决] |
回复[ 7次 ]
点击[ 2018次 ] | |
|
|
|
|
[帖 主]
[ 发表时间:2007-10-05 13:15 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:13
注册日期:2007-09-26 02:27 |
assume cs:code
data segment
db 10 dup (0)
data ends
stack segment
db 16 dup(0)
stack ends;
code segment
start:
mov ax,12666
mov bx,data
mov ds,bx
mov si,0
call dtoc
mov dh,8
mov dl,3
mov cl,2
call show_str
mov ax,4c00h
int 21h
dtoc:
push cx
push si
push bx
push dx
push ds
mov dx,0
mov bx,0
div_cur:
mov cx,0Ah
call divdw ;调用解决溢出的除法
jcxz s ;余数=0,跳出
add cx,30H ;将余数转换成ASCII码
push cx
inc bx
jmp short div_cur
s:
mov cx,bx
s1:
pop ax
mov byte ptr ds:[si],al
inc si
loop s1
ok1:
pop ds
pop dx
pop bx
pop si
pop cx
ret
divdw:
push bx
push ax
mov ax,dx
mov dx,0
div cx
mov bx,ax ;将商的高位临时放到bx中
pop ax
div cx ;上一步div的余数(在dx中)做高位,连同ax中的数据(低位)一起做被除数
mov cx,dx ;将余数给cx
mov dx,bx
pop bx
ret
show_str:
push dx
push cx
push si
push es
push di
push ax
mov ax,0B800H
mov es,ax
mov ch,0
;计算dh*160,保存(dh*160)到di中
mov ax,0A0H
mul dh
mov di,ax
;计算2dl-1,保存(dh*160)+(2*dl-1)到di中,得到字符写入显存的偏移地址di
mov ax,2
mul dl
add di,ax
mov al,cl
next_zf:
mov cl,[si]
jcxz ok
;写入字符
mov byte ptr es:[di],cl
;写入颜色
mov byte ptr es:[di+1],al
add di,2
inc si
jmp short next_zf
ok:
pop ax
pop di
pop es
pop si
pop cx
pop dx
ret
code ends
end start | | |
|
|
|
|
[第1楼]
[ 回复时间:2007-10-06 15:41 ]
[引用]
[回复]
[ top ] | |
荣誉值:106
信誉值:0
注册日期:2007-06-26 15:10 |
|
|
|
|
|
[第2楼]
[ 回复时间:2007-10-06 16:32 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:13
注册日期:2007-09-26 02:27 |
sunshine 有QQ号吗,向你学习,我的465630364 | | |
|
|
|
|
[第3楼]
[ 回复时间:2007-10-06 17:43 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:13
注册日期:2007-09-26 02:27 |
//修改后的,我的第一个存在问题,就是当数据末尾是零的时候会有问题
assume cs:code
data segment
db 10 dup (0)
data ends
stack segment
db 60 dup(0)
stack ends;
code segment
start:
mov ax,12660
mov bx,data
mov ds,bx
mov si,0
call dtoc
mov dh,8
mov dl,3
mov cl,2
call show_str
mov ax,4c00h
int 21h
;功能:将数字转换成字符后显示在屏幕上
;要求数小于65535
;参数说明:(ds数转换成字符后存储的段地址,si偏移首地址,字符存储后的末尾要为0,
ax存放dw数)
dtoc:
push cx
push si
push bx
push dx
push ds
push di
mov dx,0
mov bx,0
mov di,0
div_cur:
mov cx,0Ah
call divdw ;调用解决溢出的除法
mov bx,cx ;因为商是存放在cx中的所以要求处理的数一定要小于65535
mov cx,ax
jcxz my_s ;商=0,跳出
add bx,30H ;将余数转换成ASCII码
push bx
inc di ;di用于累计余数压入栈的次数
jmp short div_cur
my_s:
add bx,30H
mov byte ptr ds:[si],bl
mov cx,di
inc si
s1:
pop ax
mov byte ptr ds:[si],al
inc si
loop s1
ok1:
pop di
pop ds
pop dx
pop bx
pop si
pop cx
ret
;功能:避免溢出的除法
;公式:x/n=int(H/n)*65535+[rem(H/n)+L]/n
;参数:(ax,dd类型被除数的低位,dx高位,cx存放除数;)
;返回值:(dx,ax中放商,cx中放余数)
divdw:
push bx
push ax
mov ax,dx
mov dx,0
div cx
mov bx,ax ;将商的高位临时放到bx中
pop ax
div cx ;上一步div的余数(在dx中)做高位,连同ax中的数据(低位)一起做被除数
mov cx,dx ;将余数给cx
mov dx,bx
pop bx
ret
;功能:在屏幕指定位置显示字符
;参数:(dh:行号,dl:列号,cl字符的颜色属性,ds:字符的段地址,si:段偏移首地址)
;调用:要求字符末尾以0结束
show_str:
push dx
push cx
push si
push es
push di
push ax
mov ax,0B800H
mov es,ax
mov ch,0
;计算dh*160,保存(dh*160)到di中
mov ax,0A0H
mul dh
mov di,ax
;计算2dl-1,保存(dh*160)+(2*dl-1)到di中,得到字符写入显存的偏移地址di
mov ax,2
mul dl
add di,ax
mov al,cl
next_zf:
mov cl,[si]
jcxz ok
;写入字符
mov byte ptr es:[di],cl
;写入颜色
mov byte ptr es:[di+1],al
add di,2
inc si
jmp short next_zf
ok:
pop ax
pop di
pop es
pop si
pop cx
pop dx
ret
code ends
end start | | |
|
|
|
|
[第4楼]
[ 回复时间:2015-03-01 18:22 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2014-07-22 21:10 |
;王爽汇编语言课程设计1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
assume cs:code
data segment
;年份offset 0
db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
db '1993','1994','1995'
;收入offset 21*4=84=54h
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
;员工offset 42*4=168=0a8h
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
data ends
table segment
db 21 dup ('year summ ne ?? ')
table ends
code segment
start:
mov ax,data
mov ds,ax
mov si,0
mov ax,table
mov es,ax
mov di,0
call gooddata
;到此数据整理ok到table表中
mov ax,table
mov ds,ax
mov si,0
call printftable
;到此把table表中数据打印到屏幕
mov ax,4c00h
int 21h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;名称: gooddata
;功能: 整理题目中这些数据到table中
;参数: DS:SI=要整理的数据首地址
; ES:DI=整理后的table表首地址
;返回: 无
gooddata:
push ax
push bx
push cx
push dx
push si
push di
push bp
;======================
mov cx,21
mov bx,0 ;bx专门用来移动员工人数
gooddata_0:
mov ax,0[si]
mov dx,0[si+2]
mov es:0[di],ax
mov es:2[di],dx
;以上移动年份
mov ax,54h[si]
mov dx,54h[si+2]
mov es:5[di],ax
mov es:7[di],dx
;以上移动总收入
mov bp,0a8h[bx]
mov es:0ah[di],bp
;以上移动员工人数
div bp
mov es:0dh[di],ax
;以上计算人均收入并移动
add si,4
add di,10h
add bx,2
loop gooddata_0
;=======================
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;名称: show_str
;功能: 在指定位置,用制定颜色,显示一个以0结束的字符串
;参数: DH=行号(0-24)
; DL=列号(0-79)
; CL=颜色
; DS:SI=字符串首地址
;返回: 无
show_str:
push ax
push cx
push dx
push si
push di
push es
;======================
mov ax,0b800h
mov es,ax
mov al,160
mul dh
mov di,ax
mov al,2
mul dl
add di,ax
;已经设置好屏幕位置
mov ah,cl ;ah保存色彩
mov ch,0
show_str_0:
lodsb ;抓一个字符到累加器
mov cl,al ;转移字符到cl进行判断
jcxz show_str_ok ;判断是否遇到结束0
stosw ;输出字符
jmp show_str_0
show_str_ok:
;======================
pop es
pop di
pop si
pop dx
pop cx
pop ax
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;名称: divdw
;功能: 进行不会产生溢出的除法运算,被除数和商是dword,除数是word
;参数: AX=被除数低16位
; DX=被除数高16位
; CX=除数
;返回: AX=商的低16位
; DX=商的高16位
; CX=余数
divdw:
push bx
;==================
mov bx,0
xchg ax,dx ;高低互换位置
xchg dx,bx ;转移被除数低16位到bx中,也正好凑成第一次除法条件
div cx
xchg ax,bx ;转移商的高16位到bx,也正好凑成第二次除法条件
div cx
mov cx,dx ;结果余数
mov dx,bx ;商的高16位
;==================
pop bx
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;名称: dtoc
;依赖: divdw
;功能: 将word型数据转变成十进制字符串,以0结束
;参数: AX=word数据
; DS:SI=字符串
;返回: 无
dtoc:
push ax
push bx
push cx
push dx
push si
;======================
mov bx,0 ;bx用来记录入栈次数
mov dx,0 ;由于被转化的是word数据,调用divdw之前需要吧dx置0
dtoc_div:
mov cx,10 ;转10进制字符,设在除数10
call divdw
push cx ;将余数压栈保存
inc bx
mov cx,ax ;借用cx,通过jcxz判断商是否为0
jcxz dtoc_ok
jmp dtoc_div
dtoc_ok:
mov cx,bx ;将入栈此时送cx,方便出栈
dtoc_out:
pop ax
or al,30h
mov [si],ax ;出栈到指定字符串,并转化成字符ascii码
inc si ;此处故意使si加1,这样字符紧挨在一起,而且结尾正好是0
loop dtoc_out
;======================
pop si
pop dx
pop cx
pop bx
pop ax
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;名称: ddtoc
;依赖: divdw
;功能: 将dword型数据转变成十进制字符串,以0结束
;参数: AX=Dword数据低16位
; DX=Dword数据高16位
; DS:SI=字符串
;返回: 无
ddtoc:
push ax
push bx
push cx
push dx
push si
;======================
mov bx,0 ;记录入栈次数
ddtoc_div:
mov cx,10 ;置除数10
call divdw
push cx ;余数入栈
inc bx ;计数加1
mov cx,ax
or cx,dx ;DX:AX存放商,或一下,看看里面有没有1
jcxz ddtoc_ok ;利用,jcxz判断商是否为0结束,dx:ax位置上没有1就是结束
jmp ddtoc_div
ddtoc_ok:
mov cx,bx ;应出栈次数
ddtoc_out:
pop ax
or al,30h ;数字改字符
mov [si],ax
inc si ;此处故意使si加1,这样字符紧挨在一起,而且结尾正好是0
loop ddtoc_out
;======================
pop si
pop dx
pop cx
pop bx
pop ax
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;名称: printftable
;功能: 打印table表中数据到屏幕,完成课程设计1
;参数: DS:SI=表首地址
;返回: 无
printftable:
push ax
push bx
push cx
push dx
push si
push di
;=======================
mov dh,1 ;设置行号
mov cx,21
printftable_0:
mov di,cx ;CX又当计数,又要保存色彩,临时用bx保存一下
mov cl,2 ;色彩
mov dl,2 ;年的列号
mov ch,4 ;配合下面函数,这里是字符个数,如1985,4个字符
call printnchars ;调用打印字符串函数搞定
mov ax,5[si]
mov bx,7[si] ;以上2条,配合下面打印dword数到屏幕函数
add dl,18 ;总收入的列号
call printdd ;调用打印dword到屏幕函数
mov ax,0ah[si]
add dl,18
call printdw ;同理,打印员工人数数到屏幕指定位置
mov ax,0dh[si]
add dl,18
call printdw ;同理,打印平均收入数到屏幕指定位置
inc dh ;更新行数
add si,10h
mov cx,di ;cx回归,一共循环21次
loop printftable_0
;=======================
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;名称: printnchars
;功能: 在指定位置,用指定颜色,显示一个指定长度的字符串
;参数: DH=行号(0-24)
; DL=列号(0-79)
; CL=颜色
; CH=字符串长度(1-255)
; DS:SI=字符串首地址
;返回: 无
printnchars:
push ax
push cx
push dx
push si
push di
push es
;================
mov ax,0b800h
mov es,ax
mov al,160
mul dh ;计算行
mov di,ax
mov al,2
mul dl ;计算列
add di,ax
;已经定位好屏幕位置ES:DI
mov ah,cl ;色彩转移
mov cl,ch ;ch字符个数,方便循环输出
mov ch,0
printnchars_0:
lodsb ;抓一个字符到累加器
stosw ;直接送屏幕
loop printnchars_0 ;按指定个数输出字符到屏幕
;================
pop es
pop di
pop si
pop dx
pop cx
pop ax
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;名称: printdw
;依赖: dtoc
;功能: 在指定位置,用指定颜色,显示一个word数据到屏幕
;参数: DH=行号(0-24)
; DL=列号(0-79)
; CL=颜色
; AX=word数据
;返回: 无
printdw:
push si
push ds
;====================
sub sp,12 ;这里直接在栈中开辟12字节临时空间,来保存字符串,懒得去定义新的数据段
mov si,ss
mov ds,si
mov si,sp ;这里用ds:si指向在栈中开辟的空间首地址,用作保留字符串用途
call dtoc ;调用dtoc把,字符串保存到ds:si中
call show_str ;调用show_str把ds:si中字符串显示出来
add sp,12 ;归还在栈中申请的空间12字节
;====================
pop ds
pop si
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;名称: printdd
;依赖: ddtoc
;功能: 在指定位置,用指定颜色,显示一个dword数据
;参数: DH=行号(0-24)
; DL=列号(0-79)
; CL=颜色
; AX=dword数据低16位
; BX=dword数据高16位,由于dx被用来保存行列号,被迫借用bx来保存高16位
;返回: 无
printdd:
push si
push ds
;====================
xchg bx,dx ;调用下面ddtoc的需要,
sub sp,12 ;申请空间
mov si,ss
mov ds,si
mov si,sp
;ds:si指向在栈中申请的空间,用作保留字符串用途
call ddtoc
xchg bx,dx ;调用下面show_str的需要,与上面配合
call show_str
add sp,12
;====================
pop ds
pop si
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
code ends
end start | | |
|
|
|
|
[第5楼]
[ 回复时间:2021-07-07 18:23 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2021-05-27 11:02 |
|
|