- [mxl800] 不知道上个兄弟是谁,学完这本书,还是再深入学习一下C语言,顺便研究一下在C中调用汇编 12/01 09:32
- [游客] 兄弟你学完这本书准备继续学什么? 11/28 10:28
- [niuyang168] 兄弟,多谢你的指导啊,不然我还一直在错误中兴奋呢,哈哈,看过你的图解我终于明白了。欢迎以后再去指导啊 11/26 10:47
- [mxl800] 中断是有的,这在书中就提到了!谢谢提醒。我都忘了。 11/24 09:18
- [acool] “cls”一样将c:>一起置顶!这应该如何实现呢? --------------- 在汇编中还没 11/23 16:20
- [mxl800] 是啊,看来我的第十六章还得加固呀! 11/23 14:49
- [mouse] 我的理解检测题只是一个辅助手段,首先是要对检测题的每个题支都细细分析,说出他们正确与否的理由,从而提 11/23 10:53
- [mxl800] 呵呵,没想到这么久了,我这儿还放着一个错误,musicvs和niuyang168是正确的。 11/23 07:55
- [gulunhua] 呵呵,一开始的时候也觉得是有问题啊,不过在debug里实际试了一下,把里面的值填进去了,也算是找到答 11/18 09:12
- [niuyang168] 10.3的结果应该是1010h,add ax,ax 应该是两个8h相加,得到是10h,不是16h. 11/11 09:24
- [mxl800] 呵呵,可是我的胃还是不好! 09/21 16:51
- [musicvs] 哈,我看到你的名字让我想起一个名字:吗丁啉 09/20 16:13
[2008-10-29 15:35] 完善的课程设计1!
下面炫一下自己的代码,我也去论坛看过了,大家的思路基本都是一样的,但我这个就和大家的完全不一样,代码也比较紧凑,连注释和空行都算上共191行。怎么样,还可以吧?
呵呵,说来炫一下,只是因为程序通过太高兴了,其实并没有自夸的意思,把代码贴出来,可以给后面的人参考一下!以后有时间再把思路整理一下写出来!
下面是代码:
;-----------------------------程序说明-------------------------------;
;名称:ks1 ;
;功能:将data段中的数据在屏幕上按照课设要求显示出来,具体见课程设计1 ;
;思路:将data段中表示年份的21个字符串看作是二维数组,其他数据看作是一;
; 维数组,用bx来做偏移指针,si做字符串的二级指针。 ;
; 开辟一段栈空间用来保护主程序运行现场和程序运行过程的数据暂存。;
; 开辟一段数据段show_buf,用来做显示缓存。 ;
;------------------------------分割线--------------------------------;
assume cs:codesg
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'
;以上是表示21年的21个字符串
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型数据
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型数据
data ends
show_buf segment
db 80 dup (' ')
show_buf ends
stack segment
dw 32 dup (0)
stack ends
codesg segment
start:mov ax,data
mov ds,ax ;将data段的段地址存入ds中
mov ax,show_buf
mov es,ax ;将显示缓冲区的段地址存入es中
mov ax,stack
mov ss,ax
mov sp,32
mov bx,0 ;用bx作data段的偏移指针(基址)
mov di,168 ;用di来做总人数的指针
mov dh,1
mov dl,0 ;设定显示的初始位置
mov cx,21 ;设定循环次数
begin:push cx ;保存外层循环计数器
push dx ;保存显示位置
mov si,0 ;用si做字符串的二级指针
mov bp,0 ;用bp来做显示缓冲区的偏移指针
mov cx,2 ;依次将表示年份的字符送入显示缓冲区
year:mov ax,ds:[bx][si]
mov es:[bp],ax
add si,2
add bp,2
loop year
mov ax,ds:[bx+84] ;将总收入的低16位存入ax中
mov dx,ds:[bx+86] ;将总收入的高16位存入dx中
mov bp,20
push ax
push dx
call dwtoc ;将总收入转换为字符,并送入显示缓冲区的相应位置
mov ax,ds:[di]
mov dx,0
mov bp,40
call dwtoc ;将总人数转换为字符,并送入显示缓冲区的相应位置
pop dx
pop ax ;还原ax,dx,计算人均收入
mov cx,ds:[di] ;用总人数做除数
call divdw
mov bp,60
call dwtoc ;将人均收入转换为字符,并送入显示缓冲区的相应位置
mov bp,0 ;将bp重新指向显示缓冲区的起始位置
pop dx
mov cl,2
call show_str ;在指定位置显示
pop cx
add bx,4 ;将bx指向下一个年份
add di,2 ;将di指向下一个总人数
inc dh ;将显示位置定位到下一行的起始位置
mov dl,0
loop begin
mov ax,4c00h
int 21h
;--------------------------数字转为字符的子程序------------------------------;
;名称:dwtoc ;
;功能:将dword型数据转换为表示10进制数字的字符串 ;
;参数:(ax)=要转换数字的低16位,(dx)=要转换数字的高16位 ;
; (bp)=在显示缓冲区的存储起始位置 ;
;-----------------------------以下是子程序-----------------------------------;
dwtoc:push cx
push si ;保护调用程序的运行现场
mov si,0
ch_s:mov cx,10 ;开始转换,用除10取余法
call divdw ;调用divdw来取得余数
add cx,30h ;取得与数字相应的字符
push cx ;在栈中暂存
inc si ;记录取得的数字个数
mov cx,ax
add cx,dx ;判断商是否为0
jcxz ch_e ;是就跳转到标号ch_e处,否就继续运行下面的语句
jmp short ch_s ;跳转到标号ch_s处执行程序
ch_e:mov cx,si ;转换完成,将结果送入显示缓冲区的相应位置
buff:pop ax ;取出字符
mov es:[bp],al ;将字符存入显示缓冲区的相应位置
inc bp
loop buff
pop si
pop cx ;恢复调用程序的运行现场
ret ;返回调用程序
;--------------------------不会产生溢出的除法子程序------------------------;
;名称:divdw ;
;功能:进行不会产生溢出的除法运算 ;
;参数:(ax)=被除数的低16位,(dx)=被除数的高16位,(cx)=除数 ;
;返回:(ax)=商的低16位,(dx)=商的高16位,(cx)=余数 ;
;-------------------------------以下是子程序-------------------------------;
divdw:push bx
push ax ;对ax进行暂存
mov ax,dx ;将被除数的高16位存入到ax中
mov dx,0 ;将dx置0
div cx ;用除数除以被除数的高16位,商存在ax中,余数存在dx中
mov bx,ax ;用bx来暂存商的高16位
pop ax ;取出被除数的低16位
div cx ;再次进行除法运算,商存在ax中,余数存在dx中
mov cx,dx
mov dx,bx ;根据返回要求进行数据转存
pop bx
ret
;---------------------------显示字符串的子程序------------------------------;
;名称:show_str ;
;功能:将显示缓冲区中的数据显示在显示屏指定的位置,同时将显示缓冲区清空 ;
;参数:(es)=显示缓冲区的段地址,(bp)=显示缓冲区的偏移指针 ;
; (dh)=显示位置的行号,(dl)=显示位置的列号 ;
; (cl)=显示字符的属性 ;
;------------------------------以下是子程序---------------------------------;
show_str:push ds
push bx
push ax
push di
push dx
push si ;保护调用程序的运行现场
mov ax,0b800h
mov ds,ax ;用ds做显示内存的段地址
mov al,160
mul dh
mov bx,ax
mov al,2
mul dl
mov si,ax
;根据行列号计算显示的具体位置,并将行
;存入bx中,列存入si中
push cx ;对cx进行暂存
mov cx,80
show_s:mov di,cx ;保存循环次数
mov al,es:[bp]
pop cx
mov ah,cl
mov ds:[bx][si],ax
push cx
mov cx,di
mov byte ptr es:[bp],20h
inc bp
add si,2
loop show_s ;按要求显示字符
pop cx
pop si
pop dx
pop di
pop ax
pop bx
pop ds ;恢复调用程序的运行现场
ret
codesg ends
end start
[ 游客 发表于 2008-10-29 15:49 ]
恭喜博主,祝更上一层楼!!
[ mxl800 发表于 2008-10-29 16:00 ]
谢谢!谢谢!
[ 游客 发表于 2008-10-29 16:10 ]
再次验证,不断努力+坚持=搞定一切!
[ musicvs 发表于 2008-10-29 17:37 ]
哈~恭喜恭喜啊~
那个字符颜色,我还以为你的背景是白色的呢...哈
[ mxl800 发表于 2008-10-30 08:17 ]
呵呵,当初我晕了两天,所有逻辑错误和语法错误都改正了,还是不显示,我说怎么回事呢!jcw2008一说我才明白过来。就是啊,太大意了。
[ lwbfq 发表于 2008-10-30 11:05 ]
博主厉害
[ mxl800 发表于 2008-10-31 15:12 ]
谢谢楼上夸奖,不过我认为这个程序还存在一个问题,当初我为了能够让最后的显示界面清爽一点,用没有显示的地方用空格重新覆盖了一遍,所以这样一来程序运行的时间效率可能要比其他同学的方法低一些。