. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->CALL和RET指令
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  课程设计1.我感觉数据都是已知的情况下,是否应该直接将数据定义而不是以字符串来定义。  [待解决] 回复[ 1次 ]   点击[ 425次 ]  
hualongmian
[帖 主]   [ 发表时间:2008-05-28 09:01 ]   [引用]   [回复]   [ top ] 
荣誉值:6
信誉值:0
注册日期:2008-05-13 20:29
首先我先说下思路(算上三个实验和这个课程设计,用了我两天时间,头都昏了,呵呵,这个代码是我最终感觉不错的。):我看到论坛中,大家都直接将年份以字符串形式定义在data段中,可我认为,此年份数据是已知的数据,对于此课程设计来说直接定义字符串似乎有点不妥吧,所以我也将我的代码发来大家看看。
1、在数据段中,将四种数据定义为四个数组,分别以0结尾。将ds:[bx]来定位数据段中的数据,从而不必去考虑数据有多长,只要注意是双字还是单字?是单字:add bx,2(加上0占的空间)就指向了下一个数组;是双字:add bx,4就指向了下一个数组。同时我在数据段开头用了16个字节的空间来暂存将每一个数据参数转换成的字符串信息,用si来定位。
2、因为有双字数据,有单字数据,所以我定义了两个子程序sdword和sword,分别来进行数据参数为双字和单字时的调用。
3、在主程序当中直接定义行参数dh,列参数dl和颜色参数cl,调用sdword或是sword就可以了。其它操作,比如转换操作,显示操作等由sdword,sword来调用相应的子程序就可以了。
assume cs:code
stack segment
dw 24 dup(0)
stack ends
data segment
db 16 dup(0) ;字符串暂存处。
dw 1975,1976,1977,1978,1979,1980,1981,1982
dw 1983,1984,1985,1986,1987,1988,1989,1990
dw 1991,1992,1993,1994,1995,0
dd 16,22,382,1356,2390,8000,16000,24486
dd 50065,97479,140417,197514,345980,590827,803530,1183000
dd 1843000,2759000,3753000,4649000,5937000,0
dw 3,7,9,13,28,38,130,220
dw 476,778,1001,1442,2258,2793,4037,5635
dw 8226,11542,14430,15257,17800,0
dw 5,3,42,104,85,210,123,111
dw 105,125,140,136,153,211,199,209
dw 224,239,260,304,333,0
data ends
code segment
start:  mov ax,stack
        mov ss,ax
        mov sp,48
        mov ax,data
        mov ds,ax

        mov dh,4
        mov dl,1
        add bx,16
        call s_word  ;定义年份显示的地址,其为字型数据。
        add bx,2
        mov dh,4
        mov dl,7   ;定义总收入显示的地址,其为双字型数据。
        call s_dword
        add bx,4
        mov dh,4
        mov dl,16
        call s_word  ;定义人员显示的地址,其为字型数据。
        add bx,2
        mov dh,4
        mov dl,23
        call s_word  ;定义人均收入显示的地址,其为字型数据。

        mov ax,4c00h
        int 21h    ;上面的这些传递参数。
s_word:        push bp
        push dx
        push cx
        push ax
        push dx
        push si
s_word_s: mov bp,dx     ;将将要显示的地址暂存,以免和下面的指令冲突。定义一个字型参数,十进制显示。
        mov ax,[bx]   ;对于字形数据的操作。
        mov dx,0
        mov cx,ax
        jcxz s_word_ret
        mov si,0      ;此做为一个子程序来调用。
        call dtoc     ;转换十进制操作。
        mov dx,bp
        mov cl,00001111b
        mov si,0
        call show_str   ;显示操作
        add bx,2
        inc dh       ;指向下一行。
        jmp short s_word_s
s_word_ret: pop si
          pop dx
          pop ax
          pop cx
          pop dx
          pop bp
          ret
        
s_dword: push dx
        push bp
        push ax
        push cx
        push si
s_dword_s: mov bp,dx      ;定义一个双字型参数,十进制显示出来。
        mov ax,[bx]
        mov dx,[bx].2  ;对于双字形数据的操作。
        mov cx,ax
        add cx,dx       ;防止(dx)<>0,(ax)=0时跳过循环了。
        jcxz s_dword_ret
        mov si,0      
        call dtoc     ;转换十进制操作。
        mov dx,bp
        mov cl,00001111b
        mov si,0
        call show_str   ;显示操作
        add bx,4
        inc dh
        jmp short s_dword_s
s_dword_ret: pop si
           pop cx
           pop ax
           pop bp
           pop dx 
           ret
 
dtoc:   push ax
        push bx
        push cx
        push dx
        mov bx,0  ;将bx置为0,来做后面的出栈计数器
 dt_s:        mov cx,10  ;设置将要转换的进制,此处是十进制
        call divdw ;调用divdw来进行除法运算。
        add cx,30h ;转换为字符形式
        push cx    ;将字符压栈。
        inc bx           ;计数器加一。
        mov cx,ax
        jcxz dt_s0
        inc cx
        loop dt_s
        
 dt_s0:        mov cx,bx  ;将记录的入栈次数送入cx
        dec bx           ;将计数器bx减一操作。
        pop [si]
        inc si
        loop dt_s0        
        pop dx
        pop cx
        pop bx
        pop ax
        ret

divdw:  push bx
        mov bx,ax   ;将低16位暂存
        mov ax,dx
        mov dx,0
        div cx    ;进行高16位除法运算
        push ax   ;将高16计算的结果暂存
        mov ax,bx ;将低16位送入ax中,好进行低16位的除法运算。
        div cx    ;进行低16位的除法运算(dx中存有高16位的余数),计算后(ax)为返回值。
        mov cx,dx ;将余数返回。
        pop dx    ;将运算总结果的高16位返回。
        pop bx
        ret          ;子程序返回

show_str: push ax
          push bx
          push cx
          push dx
          push si   ;将用到寄存器入栈暂存。
        mov ax,0b800h
        mov es,ax   ;刚开始此命令我放在主程序当中,最后看到论坛中放在子程序当中,感觉挺好,我就改进了。  
          mov al,160
          mul dh
          add dl,dl       
          mov dh,0
          add ax,dx   ;此三步定位显示的地址,dh,dl在这里做参数好似坐标轴一样。
          mov bx,ax   ;将显示地址送入bx寄存器。
          mov ah,cl   ;将颜色参数送入字符中。
          mov si,0          
          mov ch,0
  sh_s:          mov al,[si] ;将字符串送入al中。
          mov cl,al
          jcxz sh_s0
          mov es:[bx],ax ;将字符串显示出来。
          inc cl   ;防止ds:[si]刚好为01时,loop无法循环。
          inc si ;指向下一个字符
          add bx,2 ;将显示单元指向下一个位置。
          loop sh_s
  sh_s0:  pop si
          pop dx
          pop cx
          pop bx
          pop ax
          ret
code ends
end start
我还是很模糊那个sword和sdword子程序是否可以通用??
望高手分析下。
younggay
[第1楼]   [ 回复时间:2008-05-30 10:17 ]   [引用]   [回复]   [ top ] 
荣誉值:273
信誉值:0
注册日期:2008-01-23 20:23
此年份数据是已知的数据,对于此课程设计来说直接定义字符串似乎有点不妥吧
=================
楼主的理解太格式化了。
数据形式一定要当作数据处理么?
你的年份又不参与数据运算,所以,存成字符串的形式,从程序上是正确的,从处理上是方便的。
当然,你存成了数值形式自然也可以,那就需要将数值都转换成字符串,然后在显示出来呗。明文的数值和内存中存储的数据是不一样的。只要显示出来的都是字符。
楼上不要被表象所迷惑,被格式化的思路所束缚。
至于你的程序对与错,自己去运行检验就行了。
需要登录后才能回帖 -->> 请单击此处登录
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved