. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->CALL和RET指令
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  我的子程序代码,大家也贴出自己的相互学习吧?  [待解决] 回复[ 7次 ]   点击[ 2018次 ]  
dontbend
[帖 主]   [ 发表时间: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
sunshine
[第1楼]   [ 回复时间:2007-10-06 15:41 ]   [引用]   [回复]   [ top ] 
荣誉值:106
信誉值:0
注册日期:2007-06-26 15:10
支持
dontbend
[第2楼]   [ 回复时间:2007-10-06 16:32 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:13
注册日期:2007-09-26 02:27
sunshine 有QQ号吗,向你学习,我的465630364
dontbend
[第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
feifeiluan2
[第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
13612823438
[第5楼]   [ 回复时间:2021-07-07 18:23 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2021-05-27 11:02
6
需要登录后才能回帖 -->> 请单击此处登录
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved