. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->CALL和RET指令
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  课设一:课题分析与编程.(希望能对如我一样的新手有帮助)  [待解决] 回复[ 44次 ]   点击[ 3287次 ]  
asm_sande
[帖 主]   [ 发表时间:2008-07-22 18:12 ]   [引用]   [回复]   [ top ] 
荣誉值:5
信誉值:0
注册日期:2008-07-04 19:03
课题分析: 
一、数据 
A、年份,4字节字符,须增加0结尾识别值;B、年收入总额,4字节数据,需转换成10进数字ASCII码,同时,因转10进制后其ASCII码占位最大需占用10位,加上结束识别位共占11位,共需占11字节,原4字节将远不能满足替换;C、年人数,2字节数据,转换后需占用6字节;D、年人均收益,因是dword/word计算求得,为防溢出,取与总额同位。 
根据以上情况,原数据区空间,将难以保证数据转换ASCII后空间占位的需要,需另建适合的数据区,并拷贝数据。考虑到方便显示需要,数据构建以显示行方式排列。按预计最大占位计算,年份5字节,总额11字节,人数6字节,均数11字节,即每行应构建33字节,考虑到实际情况,均数不至于满位。因此,预留转换后数位缩减至10位,共留32字节,这样方便调试时,对数据区校验。数据区。db 672 dup(0) {21*32=672} 
0~4:年份写入寻址0[...]; 5~15:总额写入寻址5[...];16~21:人数写入寻址16[...];22~31:均数写入寻址22[...]; 

二、表格结构 
   Power idea basic situation of the company            表名 
------------------------------------------------------------                    
         year     Income       Number    Average          表头 
------------------------------------------------------------ 
01234567890123456789012345678901234567890123456789      参照标 
    ****      **********       *****       *****         表体 
    ****      **********       *****       *****    
   ****      **********       *****       *****    
------------------------------------------------------------        
Tabulation date:                     

三、程序结构模块 
为方便调试和修改,应尽可能地让程序结构简单化,程序功能模块化。 
㈠拷贝计算数据至新建数据区table段 
㈡对和table段数据区的数值进行字符的ASCII转换,(注意每项均须以0结尾) 
㈢按表结构将table段数据以字符方式写入显存 

四、编程(代码经测试通过)
调试图http://www.asmedu.net/blog/user/bigimg.jsp?neighborId=12124&pic=post_1216712368578.jpg
 

assume cs:code,ds:data,SS:STACK 
data segment  
    ;年份数据,84字节 
    db "1975",'1976',"1977","1978","1979","1980","1981","1982","1983"  
    db "1984","1985","1986","1987","1988","1989","1990","1991","1992"  
    db "1993","1994","1995"  
    ;工资总额数据 84字节(21双字) 
    dd 16,22,382,1356,2369,8000,16000,24486,50065,97479,140417,197514  
    dd 345980,590872,803530,1183000,1843000,2759000,3753000,4649000,59307000  
    ;人数数据 42字节(21字) 
    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 
    ;表格结构数组,开辟21组32字节的表格内存空间 
    db 672 dup(0);21*32=672  
    db '     Power idea basic situation of the company    ',0 
    db '--------------------------------------------------',0 
    db '      year     Income       Number    Average ',0 
table ends 
STACK SEGMENT 
    ;开辟64字节栈段空间 
    Dw 32 DUP(0) 
STACK ENDS 

code segment 
pro_end: 
    mov ax,4c00h 
    int 21h 

;*********************************** 
;*******构建数值字符转换数据区*********
;*********************************** 
;按每32字节写一组数据,将数据源 
;写入数据区备转换用 
start: 
    mov ax,data 
    mov ds,ax 
    MOV AX,TABLE 
    MOV ES,AX 
    MOV AX,STACK 
    MOV SS,AX 
    MOV SP,64 
    MOV CX,21     
    mov bx,0H   ;读取双字单元寻址增量 
    mov si,0H   ;读取字单元寻址增量 
    mov di,0H   ;写入单元寻址增量 

  s1:    PUSH 00h[bx]    ;读年份数据入栈 
    PUSH 02h[bx] 
    POP ES:02H[di]  ;年份字符数据出栈写入table(4B) 
    POP ES:00H[di]   
    mov byte ptr es:04h[di],0H    ;字符窜结尾补0(1B) 

    MOV AX,054H[bx]      ;读总额 
    MOV DX,056H[bx] 
    mov ES:05[di],AX     ;总额写入(4B,为转换应准备共11B) 
    mov ES:07[di],DX 
;............................以上数据为双字单元用BX寻址 
    push cx              ;为防除法溢出调divdw子程 
    mov cx,0A8H[si] 
    call divdw           ;读年度人数,计算年人均工资 
    pop cx 
    push 0A8h[si]             ;人数读写(2B为转换应准备共6B) 
    pop ES:16[di] 
    mov es:22[di],AX ;人均工资写入(4B为转换应准备共11B) 
    mov es:24[di],dx 
;............................以上为字单元用SI寻址 
    add bx,04h     ;读年字符与总额时增量为4字节 
    add si,02H     ;读人数与均收益时增量为2字节 
    add di,32      ;写数据时每行数据间为32字节增量 
    loop s1 
;[end] 

;********************************** 
;*********数据区数值字符转换********* 
;********************************** 
;更改数据段址,对应新建数据区 

    mov ax,table 
    mov ds,ax 
    mov cx,21 
    mov bx,0 
    mov di,0 
por_d_w: 
     
    mov si,bx        ;总额换ASCII码 
    add si,5 
    mov ax,5[bx] 
    mov dx,7[bx] 
    call dtoc32 

    mov si,bx        ;人数换ASCII码 
    add si,16 
    mov ax,16[bx] 
    mov dx,0 
    call dtoc32 

    mov si,bx        ;均额换ASCII码 
    add si,22 
    mov ax,22[bx] 
    mov dx,24[bx] 
    call dtoc32 
    add bx,32 
    loop por_d_w  
;[end] 


;************************************ 
;**********数据区字符写入显存********** 
;************************************ 
;显存段址:0b800H 
;首页:0~24行,0~79列 
;显示行设置:0行表题,1行注释线,2行表头, 
;                 3~24行表体 
;显示列设置:6~9列:年份;16~26列 总额; 
;            30~35列人数;40-50列 均数 
;数据区:段址 table。 
;起始单元si:年份00+行*32;总额05+行*32; 
;        人数16+行*32;均数22+行*32;     

    mov ax,table 
    mov ds,ax 
    mov cx,21 
    mov bx,0 
    mov dh,10 
pro_show_start: 
    push cx 
    mov cx,00001010b  
    mov ax,32 

    mul bl        ;年份写屏 
    mov dl,6 
    mov si,ax 
    call show_str 

    mov dl,16        ;总额写屏 
    add ax,5 
    mov si,ax 
    call show_str 

    mov dl,30        ;人数写屏 
    add ax,11 
    mov si,ax 
    call show_str 

    mov dl,40        ;均数写屏 
    add ax,6 
    mov si,ax 
    call show_str     
    inc bx 
    inc dh 
    pop cx 
    loop pro_show_start 

    mov cx,00001100b ;表题写屏     
    mov dh,6 
    mov dl,0 
    mov si,672 
    call show_str 
    mov cx,00001111b ;表头线写屏 
    mov dh,7 
    mov si,723 
    call show_str 
    mov cx,00001111b ;表头栏写屏 
    mov dh,8 
    mov si,774 
    call show_str 
                          

    jmp pro_end ;转至程序结束点 

;[end] 


;********★★★★★********* 
;         子程序区 
;********↓↓↓↓↓↓↓↓↓********* 


;******************************************** 
;入口:Dtoc32 
;功能:将DWord数据转化为10进制的字符窜。并以单元数值 
;        0做结尾符。 
;入参:DX=预转为10进制的数据高16位,AX=预转为10进制的 
;      数据低16位,字型。DS:si指向存放字符窜的首地址。 
;回参:无 
;******************************************** 
dtoc32: 
    push ax 
    push bx 
    push cx 
    push dx 
    push di 
    push si 

    mov bx,0 
    mov di,si 
dtoc32_s: 
    mov cx,10 
    call divdw ;dx高16位;ax低16位;cx余数 
    add cx,30h 
    mov ds:[si],cl 
    inc si 
    inc bx 
    mov cx,ax 
    jcxz dtoc32_end 
    jmp dtoc32_s 
dtoc32_end: 

    mov cx,bx 
    mov si,di 
dtoc32_f1:     
    mov al,ds:[si] 
    push ax 
    inc si  
    loop dtoc32_f1 

    mov cx,bx 
    mov si,di 
dtoc32_f2:     
    pop ax 
    mov ds:[si],al 
    inc si 
    loop dtoc32_f2 
    mov byte ptr ds:[si],0H 


    pop si 
    pop di 
    pop dx 
    pop cx 
    pop bx 
    pop ax 
    ret 
;[end] 

;*********************************************** 
;入口:DIVDW 
;功能:进行不会溢出的DWORD/WORD除法。 
;入参:dx=被除数高16位;ax=被除数低16位; 
;      cx=16位除数,适用被除数DWORD,除数WORD。 
;回参:dx=商的高16位;ax=商的低16位;cx=余数 
;*********************************************** 
divdw:     
    push bx 

    mov bx,ax 
    mov ax,dx 
    mov dx,0h 
    div cx 
    push ax 
    mov ax,bx 
    div cx 
    mov cx,dx 
    pop dx 

    pop bx 
    ret 
;[end] 

;************************************************* 
;名称:show_str  入口标号 
;功能:在指定行与列,按指定属性,显示一个以0结尾的字符窜。 
;入参:DH=行号(0-24),DL=列号(0-79),CL=显示属性, 
;      DS:SI指向字符窜首地址 
;回参:无 
;************************************************* 
show_str:     
    push ax 
    push bx 
    push cx 
    push dx 
    push es 
    push di 
    push si 
     
    mov bx,0h 
    mov ax,160 
    mov bl,dh 
    mul bl 
    mov bl,dl 
    add bx,bx 
    add ax,bx 
    mov bx,ax 
    mov ax,0b800h 
    mov es,ax 
    mov di,0 
    mov dh,cl 
show_str_s: 
    mov cl,ds:[si] 
    jcxz show_str_end 
    mov dl,cl 
    mov es:[bx+di],dx 
    inc si 
    inc di 
    inc di 
    jmp short show_str_s 
show_str_end: 
    pop si 
    pop di 
    pop es 
    pop dx 
    pop cx 
    pop bx 
    pop ax 
    ret 
;[end]     



code ends 
end start 


;原文在博客上http://www.asmedu.net/blog/user/postcontent.jsp?neighborId=12124&kindId=15534&postId=21232&readSg=1&vs=1
deepblue
[第1楼]   [ 回复时间:2008-07-22 19:44 ]   [引用]   [回复]   [ top ] 
荣誉值:56
信誉值:0
注册日期:2008-01-19 14:51
从分析到程序,脉络清晰,
顶一下!
hnuzyf
[第2楼]   [ 回复时间:2008-07-23 17:22 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2008-07-18 09:32
恩写得不错吧,思路很清楚。
asm_sande
[第3楼]   [ 回复时间:2008-07-25 22:42 ]   [引用]   [回复]   [ top ] 
荣誉值:5
信誉值:0
注册日期:2008-07-04 19:03
嗯,我的感觉是在学习中,弄懂所以然很重要.
debugk
[第4楼]   [ 回复时间:2008-07-27 11:09 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2008-06-13 10:30
非常好,顶!
fancx
[第5楼]   [ 回复时间:2008-10-24 01:21 ]   [引用]   [回复]   [ top ] 
荣誉值:3
信誉值:0
注册日期:2008-08-02 09:52
高手,实在是高手!
奇强。
fancx
[第6楼]   [ 回复时间:2008-10-28 13:25 ]   [引用]   [回复]   [ top ] 
荣誉值:3
信誉值:0
注册日期:2008-08-02 09:52
mov bx,0h  
    mov ax,160  
    mov bl,dh  
    mul bl  
    mov bl,dl  
    add bx,bx  
    add ax,bx  
    mov bx,ax  
    mov ax,0b800h  
    mov es,ax  
    mov di,0  
    mov dh,cl  
show_str_s:  
    mov cl,ds:[si]  
    jcxz show_str_end  
    mov dl,cl  
    mov es:[bx+di],dx  
    inc si  
    inc di  
    inc di  
    jmp short show_str_s  
show_str_end:  
——————————————————————————————————————————————————————————————
以上代码,能不能给我们初学着注释注释呢?
比较难懂哦。
orsprite
[第7楼]   [ 回复时间:2008-10-31 19:06 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2008-10-31 17:48
注释很详细
aukeys
[第8楼]   [ 回复时间:2008-11-17 21:03 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2008-11-08 21:55
有个问题不明白
dtoc32_s:  
    mov cx,10  
    call divdw ;dx高16位;ax低16位;cx余数  
    add cx,30h  
    mov ds:[si],cl  
    inc si  
    inc bx  
    mov cx,ax  
    jcxz dtoc32_end 

以上代码,返回高位DX,低位AX,余CX
如果遇到10000000h除以10h高位DX中为0100,低位AX中为0000
那么AX传送CX然后用JCXZ跳转,这样的结果肯定不正确啊
wuzy
[第9楼]   [ 回复时间:2009-01-07 13:09 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2008-11-15 13:47
高手,顶一下。
zcouyangpeng
[第10楼]   [ 回复时间:2009-01-07 21:32 ]   [引用]   [回复]   [ top ] 
荣誉值:35
信誉值:44
注册日期:2008-09-03 21:36
强。
272003327
[第11楼]   [ 回复时间:2009-01-07 23:13 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2008-09-29 21:55
格式清晰,可读性高。我要向你学习!
yangle0125
[第12楼]   [ 回复时间:2009-02-03 21:42 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2008-11-09 12:50
强是挺强,但是最后一个数据不对。原因是dtoc32_s子程序不对,跳转的时候要确保dx,ax都是零了才可以跳。
比如可以
mov cx,ax
add cx,dx
jcxz ...
当然还有别的判断方法
yangle0125
[第13楼]   [ 回复时间:2009-02-03 21:43 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2008-11-09 12:50
最后一个数据应该是333,楼主的是3331哦
beyondchxff
[第14楼]   [ 回复时间:2009-03-01 09:12 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2008-12-10 00:00
为什么说4字节数转化成10进制ASCII码就要占10位了呢,有点想不明白
aten
[第15楼]   [ 回复时间:2009-03-24 17:11 ]   [引用]   [回复]   [ top ] 
荣誉值:4
信誉值:0
注册日期:2008-12-11 08:43
进来看看,我还没做课设1,就先不看啦!
mark!
回头再来看看!呵呵,分析得好像很详细!顶一个!
qizui
[第16楼]   [ 回复时间:2009-04-02 15:45 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2009-03-28 12:51
按预计最大占位计算,年份5字节,总额11字节,人数6字节,均数11字节,即每行应构建33字节,考虑到实际情况,均数不至于满位。因此,预留转换后数位缩减至10位,共留32字节,这样方便调试时,对数据区校验。




上面这话是啥意思啊,年份4字节,再加上末位的0,一共5字节,总额怎么就是11字节了呢,59307000,一共才8字节,末位加0,才9字节。人数6字节,均数9字节,5+9+6+9=29字节啊,每列中间留一个字节空格吗?,怎么安排的?
qizui
[第17楼]   [ 回复时间:2009-04-02 15:54 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2009-03-28 12:51
哦,我懂了,4字节数据就是FFFF  FFFF=65535  65535 一共10位,加个字符识别码就是11位,按最大情况考虑
那么均数不不至于满位,是怎么想出来的?

显示缓冲区是一个字符两个字节,一个放ASSII码,另一个放字符属性,那么空格是怎么弄出来的
sinawear
[第18楼]   [ 回复时间:2009-05-16 18:21 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:5
注册日期:2009-03-25 17:31
哦,我懂了,4字节数据就是FFFFFFFF=4294967295 一共10位,加个字符识别码就是11位,按最大情况考虑
那么均数不不至于满位,是怎么想出来的?

显示缓冲区是一个字符两个字节,一个放ASSII码,另一个放字符属性,那么空格是20h.
yangtuan2010
[第19楼]   [ 回复时间:2009-06-05 09:43 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2009-06-03 15:34
不懂
hansonjan
[第20楼]   [ 回复时间:2009-06-06 13:07 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2009-05-13 22:27
只能显示到1989年份。后面的数据就没法显示了。
我10000000/10怎么转成字符啊?一开始除就余数是0了。
卡在这,做不下去了。才来看看!
还是不懂!汇编真头痛.
cfcxg
[第21楼]   [ 回复时间:2009-06-18 11:01 ]   [引用]   [回复]   [ top ] 
荣誉值:9
信誉值:3
注册日期:2008-12-21 10:26
对于程序设计一,我思索了许久,开始以为在原先的程序上加些程序调用就可以了,可实际作起来确让我遇到很的麻烦,硬着头皮写了好些代码,可是执行起来确得不到结果,现在看到楼主的设计,让我感受最深的就是,程序员的作事严禁,思路清晰,注重细节,我觉得我作得还很不够,看来脑子里不能急于求成,凡事要一步一步的落实!
tsembrace
[第22楼]   [ 回复时间:2009-07-16 23:44 ]   [引用]   [回复]   [ top ] 
荣誉值:31
信誉值:3
注册日期:2009-06-15 19:20
深夜拜读!
受益匪浅,呵呵。谢谢LZ分享。
就是一个小问题,如12楼所说。
zw_524
[第23楼]   [ 回复时间:2009-07-31 12:57 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2008-11-23 19:07
思路清晰,语言精简,学习了,顶一下!
aaaabbbb12345
[第24楼]   [ 回复时间:2009-09-27 16:55 ]   [引用]   [回复]   [ top ] 
荣誉值:4
信誉值:9
注册日期:2009-09-16 17:09
这设计1快折磨我一星期了,有感觉,结果出不来
wtan
[第25楼]   [ 回复时间:2010-01-10 13:05 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2010-01-03 08:56
思路很清晰,不过第12楼说得对,判断失误,结果明显有问题
dos
[第26楼]   [ 回复时间:2010-01-21 20:18 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2007-10-14 13:42
有个问题不明白
dtoc32_s:  
    mov cx,10  
    call divdw ;dx高16位;ax低16位;cx余数  
    add cx,30h  
    mov ds:[si],cl  
    inc si  
    inc bx  
    mov cx,ax  
    jcxz dtoc32_end 

以上代码,返回高位DX,低位AX,余CX
如果遇到10000000h除以10h高位DX中为0100,低位AX中为0000
那么AX传送CX然后用JCXZ跳转,这样的结果肯定不正确啊
-----------------------------------------------------------
强是挺强,但是最后一个数据不对。原因是dtoc32_s子程序不对,跳转的时候要确保dx,ax都是零了才可以跳。
比如可以
mov cx,ax
add cx,dx
jcxz ...
当然还有别的判断方法
01010100101010010100101010010100101010010100101010011011101
如果遇到13fff6h/0Ah得(dx)=0001h,(ax)=0ffffh呢
-----------------------------------------------------------
只能显示到1989年份。后面的数据就没法显示了。
我10000000/10怎么转成字符啊?一开始除就余数是0了。
卡在这,做不下去了。才来看看!
还是不懂!汇编真头痛.
-----------------------------------------------------------
课设1中程序要显示的数据有些已经大于65535d(0ffffh),应该写一个新的数据到字符串转化的子程序,
因为(ax)=dword型数据的低16位,(dx)=dword型数据的高16位,求余数时要用到divdw子程序,返回
(dx)=商的高16位,(ax)=商的低16位,(cx)=余数,除到商为0(即(dx)=0且(ax)=0)时,各位的值就全部求出了,判断商值部分:
      mov cx,dx             ;先检查商的高位是否为0
      jcxz ifaxz            ;如果商的高位为0,则检查商的低位是否为0
      jmp short 求余数标号  ;如果商的高位不为0,则商不为0,则继续求余数
ifaxz:mov cx,ax             ;检查商的低位是否为0
      jcxz 跳出求余数标号   ;如果商的低位为0,且商的高位为0,则商为0,则求余结束
      jmp short 求余数标号  ;如果商的低位不为0,则商不为0,则继续求余数
ldlihuanfa
[第27楼]   [ 回复时间:2010-01-23 13:54 ]   [引用]   [回复]   [ top ] 
荣誉值:6
信誉值:0
注册日期:2009-12-18 19:53
进来学习一下思路
ldlihuanfa
[第28楼]   [ 回复时间:2010-01-23 14:39 ]   [引用]   [回复]   [ top ] 
荣誉值:6
信誉值:0
注册日期:2009-12-18 19:53
dtoc32_f2:      
    pop ax  
    mov ds:[si],al  
    inc si  
    loop dtoc32_f2  
    mov byte ptr ds:[si],0H  
最后一句不是太明白,
ldlihuanfa
[第29楼]   [ 回复时间:2010-01-23 16:39 ]   [引用]   [回复]   [ top ] 
荣誉值:6
信誉值:0
注册日期:2009-12-18 19:53
思路真的很清楚,具体的细节上可能还没完全搞懂,但含义完明了
qiangzi
[第30楼]   [ 回复时间:2010-01-26 16:26 ]   [引用]   [回复]   [ top ] 
荣誉值:4
信誉值:6
注册日期:2010-01-07 10:37
思路清晰,顶一下
goodbye
[第31楼]   [ 回复时间:2010-03-04 11:04 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2009-12-30 08:49
思路很清晰,不过感觉开辟的内存空间太大,反复读写,效率会不会不高...
mathson
[第32楼]   [ 回复时间:2010-09-11 05:59 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2010-09-11 05:48
marked
toopoor
[第33楼]   [ 回复时间:2010-10-12 21:40 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2010-09-27 17:38
mov byte ptr es:04h[di],0H    ;字符窜结尾补0(1B)
逐句代码去掉也行,因为你的table初始化的时候都是零
toopoor
[第34楼]   [ 回复时间:2010-10-12 23:02 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2010-09-27 17:38
另外在金额是0a000000h,人数是0ah时候,显示到屏幕上的金额是0
toopoor
[第35楼]   [ 回复时间:2010-10-13 11:33 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2010-09-27 17:38
按照27楼的思路修改了dtoc32子程序,果然好使。

;********************************************  
;入口:Dtoc32  
;功能:将DWord数据转化为10进制的字符窜。并以单元数值  
;        0做结尾符。  
;入参:DX=预转为10进制的数据高16位,AX=预转为10进制的  
;      数据低16位,字型。DS:si指向存放字符窜的首地址。  
;回参:无  
;********************************************  
dtoc32:  
    push ax  
    push bx  
    push cx  
    push dx  
    push di  
    push si  

    mov bx,0  
    mov di,si  
dtoc32_s:  
    mov cx,10  
    call divdw ;dx高16位;ax低16位;cx余数  
    add cx,30h  
    mov ds:[si],cl  
    inc si  
    inc bx  
    mov cx,dx
    jcxz ifdxz                  ;如果商的高位不为零,则商不为零,继续求余数
    jmp dtoc32_s
ifdxz:mov cx,ax                ;检查商的低位是否为0
    jcxz dtoc32_end          ;如果商的低位为零,且商的高位也为零,则商为零,求余结束。
    jmp dtoc32_s  
dtoc32_end:  

    mov cx,bx  
    mov si,di  
dtoc32_f1:      
    mov al,ds:[si]  
    push ax  
    inc si   
    loop dtoc32_f1  

    mov cx,bx  
    mov si,di  
dtoc32_f2:      
    pop ax  
    mov ds:[si],al  
    inc si  
    loop dtoc32_f2  
    mov byte ptr ds:[si],0H  


    pop si  
    pop di  
    pop dx  
    pop cx  
    pop bx  
    pop ax  
    ret
ckv
[第36楼]   [ 回复时间:2010-10-31 08:14 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2010-10-02 07:00
努力学习中。。。。。
huang425618
[第37楼]   [ 回复时间:2010-11-08 22:35 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2010-08-20 21:47
大部份都看懂了,只有一小部分看不懂,看懂的部分进行参考后,我终于写出自己的程序并通过检测了,很感谢楼主的无私奉献,可是我回过头来看看,发现还是有一小部分没懂,很是郁闷,看来自己的悟性不行,只能勤奋的去学了.
dayu003
[第38楼]   [ 回复时间:2011-01-14 10:18 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2011-01-02 16:13
无语了。。。。都怎么学的呀??
16进制数的10000000处以十进制的10还说一开始商就为零了,27楼莫名其妙的弄个判断程序,我汗,瀑布汗!

都回去看书去,别跑这儿丢人现眼!
楼主这个程序写的一般般,把书读好了能写大把比这好的
jiafangbai
[第39楼]   [ 回复时间:2011-01-19 14:05 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2010-10-29 23:22
过于冗长,做到正确输出并不难,关键看方法的科学性。
aibvfhpia
[第40楼]   [ 回复时间:2011-01-28 01:15 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2010-12-20 11:44
DATA  SEGMENT
              DB        '1975','1976','1977','1978','1979','1980','1981','1982','1983','1984','1985','1986','1987','1988','1989','1990','1991','1992','1993','1994','1995'
              DD        16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514,345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
              DW        3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226,11542,14430,15257,17800
              DW        500 DUP (0)
        DATA  ENDS
        CODE  SEGMENT
              ASSUME    CS:CODE,DS:DATA
      START:  MOV       AX,DATA
              MOV       DS,AX
              MOV       AX,0B800H
              MOV       ES,AX
              MOV       SI,0
              MOV       DI,0
              MOV       BX,0
              MOV       BP,0
              CALL      PUTINONE
              CALL      PUTINTWO
              CALL      PUTINTHREE
              CALL      PUTINTFOUR
              
       OVER:  MOV       AX,4C00H
              INT       21H
                            
   PUTINONE:  PUSH      SI
              PUSH      DI
              PUSH      BX
              PUSH      BP

              MOV       CX,21
          S:  PUSH      CX
              MOV       CX,4
              MOV       BX,0
              MOV       BP,0
         S1:  MOV       AL,DS:[BX+DI]
              MOV       AH,8H
              MOV       ES:[SI+BP+644],AL
              MOV       ES:[SI+BP+645],AH
              INC       BX
              ADD       BP,2
              LOOP      S1
              ADD       DI,4
              ADD       SI,160
              POP       CX
              LOOP      S
              
              POP       BP
              POP       BX
              POP       DI
              POP       SI
              
              RET

   PUTINTWO:  PUSH      BX
              PUSH      SI
              PUSH      DI
              PUSH      BP
              MOV       CX,21
         S4:  PUSH      CX
              MOV       AX,DS:[BX+84]
              MOV       DX,DS:[BX+86]
         S0:  MOV       SI,10
              PUSH      AX
              MOV       AX,DX
              MOV       DX,0
              DIV       SI
              MOV       CX,AX
              POP       AX
              DIV       SI
              MOV       SI,DX
              MOV       DX,CX
              MOV       CX,AX
              ADD       CX,DX
              PUSH      SI
              ADD       DI,1
              JCXZ      OK
              JMP       SHORT S0
         OK:  MOV       CX,DI
              MOV       SI,0
         S2:  POP       AX
              ADD       AL,30H
              MOV       AH,8H
              MOV       ES:[BP+SI+664],AL
              MOV       ES:[BP+SI+665],AH
              ADD       SI,2
              LOOP      S2
              ADD       BX,4
              ADD       BP,160
              MOV       DI,0
              POP       CX
              LOOP      S4
              POP       BP
              POP       DI
              POP       SI
              POP       BX
              RET

 PUTINTHREE:  PUSH      BX
              PUSH      SI
              PUSH      DI
              PUSH      BP
                                                         
              MOV       CX,21
         S5:  PUSH      CX
              MOV       AX,DS:[BX+168]
         S6:  MOV       SI,10
              DIV       SI
              PUSH      DX
              ADD       DI,1
              MOV       DX,0
              MOV       CX,AX
              JCXZ      OK1
              JMP       SHORT S6
        OK1:  MOV       CX,DI
              MOV       SI,0
         S7:  POP       AX
              ADD       AL,30H
              MOV       AH,8H
              MOV       ES:[684+BP+SI],AL
              MOV       ES:[685+BP+SI],AH
              ADD       SI,2
              LOOP      S7
              ADD       BX,2
              ADD       BP,160
              MOV       DI,0
              POP       CX
              LOOP      S5
              POP       BP
              POP       DI
              POP       SI
              POP       BX
              RET
 PUTINTFOUR:  MOV       CX,21
         S8:  PUSH      CX
              MOV       AX,DS:[BX+84]
              MOV       DX,DS:[BX+86]
              MOV       CX,DS:[SI+168]
              DIV       CX
              MOV       DX,0
         S9:  MOV       CX,10
              DIV       CX
              PUSH      DX
              ADD       DI,1
              MOV       DX,0
              MOV       CX,AX
              JCXZ      OK2
              JMP       SHORT   S9
        OK2:  MOV       CX,DI
              MOV       DI,0
        S10:  POP       AX
              ADD       AL,30H
              MOV       AH,8H
              MOV       ES:[704+BP+DI],AL
              MOV       ES:[705+BP+DI],AH
              ADD       DI,2
              LOOP      S10
              ADD       BX,4
              ADD       SI,2
              ADD       BP,160
              MOV       DI,0
              POP       CX
              LOOP      S8
              RET
                            
        CODE  ENDS
              END       START
                   
刚写完,流水式做法。。经得住测试,有高手请帮改进下   。。。
youguiqing
[第41楼]   [ 回复时间:2011-03-12 21:40 ]   [引用]   [回复]   [ top ] 
荣誉值:6
信誉值:0
注册日期:2009-12-03 21:13
你们的dtoc转换数字子程序都有问题像655360等这样的数字就无法显示 655360=a0000h
youguiqing
[第42楼]   [ 回复时间:2011-03-12 21:42 ]   [引用]   [回复]   [ top ] 
荣誉值:6
信誉值:0
注册日期:2009-12-03 21:13
assume cs:code
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,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,11430,15257,17800
data ends
stack segment
dw 16 dup (0)
stack ends
code segment
              start:mov ax,data
                  mov ds,ax
                   mov ax,stack
                   mov ss,ax
                   mov sp,32
                   mov ax,0b800h
                   mov es,ax
                   mov bx,0
                   mov bp,0
                   mov di,0
                   mov cx,21
                s: mov si,10      ;21次loop    注意SI的值为列数一定要清10后以bp为变量每次加160
                push cx     ;保存外层CX值
                   mov cx,4       ;内层年份4次
                   push bx    ;因为loop后bx会变,所以这里先保存
                n1:push [bx]        ;年份  从第10列开始显示    
                   pop es:[bp+si]
                   mov es:1[bp+si],02  ;加色
                   inc bx
                   add si,2
                   loop n1
                   pop bx
                   mov si,40     ;收入从40列开始
                   mov ax,84[bx]
                   mov dx,86[bx]
                   call dtoc
                   mov si,80    ;人数从80列开始
                   mov ax,168[di]
                   mov dx,0
                   call dtoc
                   mov si,120   ;人均收入从120列开始
                   mov ax,84[bx]
                   mov dx,86[bx]
                   mov cx,168[di]
                   call divdw
                   call dtoc
                   add bx,4     ;年份和收入为4字节,每次加4
                   add di,2     ;人数为2字节每次加2
                   add bp,160   ;bp每次加160用来换行
                   pop cx
                   loop s
                   mov ax,4c00h
                   int 21h
           divdw: push bx            ;这是大除法子程序dx+ax除以cx后商高为DX低位为AX余数为CX
              push ax
               mov ax,dx
               mov dx,0
               div cx
               mov bx,ax
               pop ax
               div cx
               mov cx,dx
               mov dx,bx
               pop bx
               ret
          dtoc:push bx     ;这是把高16位=dx低16位=ax的数转化为ascll码显示在屏幕上的子程序
                push cx
                  mov bx,0   ;一定要重置为0
            b1:  mov cx,10      ;注意用商来判断一定要先存余数后再判断
               call divdw
                 mov ch,02h ;加上显示的颜色
                 add cl,30h ;加上30h用ASCLL码显示
                 push cx   ;保存加色后的余数到载
                 inc bx  ;用来记录push了几次
                  mov cx,ax;下面是判断商是否为0
                  jcxz jdx
                jmp b1
          jdx:   mov cx,dx
               jcxz ok 
                 jmp b1
        ok:     mov cx,bx ;push几次直接pop 几次
           a1: pop es:[bp+si]   ;这里的bp和si直接来至主程序
                add si,2
                 loop a1
                 pop cx
                 pop bx
                 ret 
code ends
end start
879439166
[第43楼]   [ 回复时间:2011-03-31 09:33 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2011-03-16 22:52
写的很详细,谢谢!!!
dallas48
[第44楼]   [ 回复时间:2011-06-09 16:54 ]   [引用]   [回复]   [ top ] 
荣誉值:4
信誉值:2
注册日期:2011-01-06 10:33
mov bx,0h                                                                                                  
    mov ax,160                          ;每行160个字节
    mov bl,dh                                  ;行数
    mul bl                                  ;结果AX就是第(dh)行的显存地址
        
    mov bl,dl  
    add bx,bx                                  ;每个字符占俩字节,因为需要一个字节存储颜色属性
    add ax,bx  
    mov bx,ax                                 ;到这里应该是(dh)行(dl)列的显存地址 
        
    mov ax,0b800h  
    mov es,ax                                  
    mov di,0  
    mov dh,cl                                  ;颜色属性存入dh
show_str_s:  
    mov cl,ds:[si]                  
    jcxz show_str_end                  ;当cx=0即遇见结束字符0时,跳转到show_str_end
    mov dl,cl  
    mov es:[bx+di],dx  
    inc si                                  ;源字符每次取一个
    inc di                                  ;目的地址每次+2
    inc di  
    jmp short show_str_s  
show_str_end:  
——————————————————————————————————————————————————————————————
以上代码,能不能给我们初学着注释注释呢?
比较难懂哦。
------------------
需要登录后才能回帖 -->> 请单击此处登录
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved