17066038 发表于 2016-8-3 08:48:59

汇编语言-实验十-屏幕显示12666

分享一下代码和学习心得
1、用到loop s时,自然会修改cx的值,要小心使用cx时用loop指令,jmp是个不错的选择,或将cx入栈

2、栈的使用,子程序中将寄存器的值入栈,运行完子程序后将寄存器的值出栈,不会影响指针sp的值,只需要做到栈足够大,在子程序的运行过程中栈不越界,否则会影响到调入内存中的其他值,如:可能改变你的指令,从而影响程序的正确执行。

代码分享:
(这个代码实现的是:显示出来的是66621,倒序,做之前没有看答案)
assume cs:code

data segment
db 10 dup(0)                        ;16B,准备放置屏幕要显示的内容
data ends

stack segment
dw 16 dup(0)                        ;32B
stack ends

code segment
start:
        mov ax,stack
        mov ss,ax
        mov sp,32

        mov ax,12666                ;初始给定的word型数据<65536,最大5位数

        mov bx,data
        mov ds,bx                ;初始给定的十进制值及颜色值的存放位置
        mov si,0

        call dtoc

        mov dh,8                ;给定显示的位置及颜色要求:8行3列、绿色
        mov dl,3
        mov cl,2
        call show_str
        mov ax,4c00h
        int 21h

dtoc:
        ;此子程序要求给定16位被除数在寄存器ax中,除数为8位=10
        ;转换结果存在ds:中
        ;此程序要求栈段的长度为32B

        push ax
        push bx
        push cx
        push dx
        push si
       
        mov dx,10                ;设定除数
        mov bx,ax
dtoc_s:        mov ah,0
        mov al,bh
        div dl
        mov ch,al
        mov al,bl
        div dl
        mov cl,al

        add ah,30h
        mov ds:,ah                ;余数写入内存ds:中
        jcxz dtoc_ok
        inc si
        mov bx,cx
        jmp dtoc_s
       
       
dtoc_ok:
        pop si
        pop dx
        pop cx
        pop bx
        pop ax
        ret

show_str:
        ;此子程序要求给定值在相应的寄存器中:行=dh,列=dl,颜色值=cl
        ;此程序要求栈段的长度为32B

        push ds
        push es
        push si
        push di
        push ax
        push bx
        push cx
        push dx
       
        ;求目标地址
        mov ax,0b800h
        mov es,ax
        mov di,0
       
        mov ax,0
        mov al,160
        dec dh                        ;从0行开始计数
        add dh,2                ;显存从第3行开始显示
        mul dh
        add di,ax

        mov ax,0
        mov al,2
        dec dl
        mul dl
        add di,ax

        mov ah,cl
        mov cx,0                ;清空cx的值

        ;向目标地址写入数据       
show_str_s:       
        mov cl,ds:
        jcxz show_str_ok
        mov al,ds:
        mov es:,al
        mov es:,ah
        inc si
        add di,2
        jmp show_str_s

show_str_ok:       
        pop dx
        pop cx
        pop bx
        pop ax
        pop di
        pop si
        pop es
        pop ds
        ret       

code ends
end start

17066038 发表于 2016-8-3 09:07:59

oneidea:子程序不会改变sp的值,不用考虑入栈的问题,我在写此程序时还误考虑sp入栈的问题

17066038 发表于 2016-8-3 10:47:38

改进了程序,这次竟然忘记了将每次求得的余数转换为ASCII码,汗!!!显示为乱码
辛苦的每步debug-t才发现。assume cs:code

data segment
db 10 dup(0)                        ;16B,准备放置屏幕要显示的内容
data ends

stack segment
dw 16 dup(0)                        ;32B
stack ends

code segment
start:
        mov ax,stack
        mov ss,ax
        mov sp,32

        mov ax,data
        mov ds,ax                ;初始给定的十进制值及颜色值的存放位置
        mov si,0
        mov di,0

        mov ax,12666                ;初始给定的word型数据<65536,最大5位数
        call dtoc_4bdiv2b

        mov dh,8                ;给定显示的位置及颜色要求:8行3列、绿色
        mov dl,3
        mov cl,2
        call show_str

        mov ax,4c00h
        int 21h

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
show_str:
        ;参数:行=dh,列=dl,颜色值=cl
        ;返回值:将内存中的ASCII码内容显示出来

        ;此子程序要求给定值在相应的寄存器中:行=dh,列=dl,颜色值=cl
        ;此程序要求栈段的长度为32B

        push ds
        push es
        push si
        push di
        push ax
        push bx
        push cx
        push dx
       
        ;求目标地址
        mov ax,0b800h
        mov es,ax
        mov di,0
       
        mov ax,0
        mov al,160
        dec dh                        ;从0行开始计数
        add dh,2                ;显存从第3行开始显示
        mul dh
        add di,ax

        mov ax,0
        mov al,2
        dec dl
        mul dl
        add di,ax

        mov ah,cl
        mov cx,0                ;清空cx的值

        ;向目标地址写入数据       
show_str_s:       
        mov cl,ds:
        jcxz show_str_ok
        mov al,ds:
        mov es:,al
        mov es:,ah
        inc si
        add di,2
        jmp show_str_s

show_str_ok:       
        pop dx
        pop cx
        pop bx
        pop ax
        pop di
        pop si
        pop es
        pop ds
        ret       

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
dtoc_4bdiv2b:
        ;参数:数据由ax给出
        ;返回值:转换为10进制数的ASCII码存放在内存ds:0处,正常顺序存放

        ;此子程序要求被除数最大为32位,除数最大为16位,直接按照16位除数进行运算
        ;此程序要求栈段的长度为32B

        push ax
        push bx
        push cx
        push dx
        push si

        mov di,0
dtoc_4bdiv2b_s:
        mov dx,0        ;被除数、除数最大16位,不会溢出,直接div即可
        mov bx,10
        div bx
        add dx,30h        ;余数在dx中,实际只会在dl中,dh为0
        push dx                ;切勿忘记+30h,转换为ASCII码
        inc di                ;计数1次
        mov cx,ax
        jcxz dtoc_4bdiv2b_s2
        jmp short dtoc_4bdiv2b_s
dtoc_4bdiv2b_s2:
        mov cx,di        ;将计数转入cx进行loop循环
dtoc_4bdiv2b_s1:
        pop ax
        mov ds:,al
        inc si
        loop dtoc_4bdiv2b_s1

dtoc_4bdiv2b_ok:
        pop si
        pop dx
        pop cx
        pop bx
        pop ax
        ret       
       
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

dtoc_2bdiv1b:
        ;参数:ax给出被除数
        ;返回值:转换结果存在ds:中,逆序存放

        ;此子程序要求给定16位被除数在寄存器ax中,除数为8位=10
        ;此程序要求栈段的长度为32B

        push ax
        push bx
        push cx
        push dx
        push si
       
        mov dx,10                ;设定除数
        mov bx,ax
dtoc_2bdiv1b_s:
        mov ah,0
        mov al,bh
        div dl
        mov ch,al
        mov al,bl
        div dl
        mov cl,al

        add ah,30h
        mov ds:,ah                ;余数写入内存ds:中
        jcxz dtoc_2bdiv1b_ok
        inc si
        mov bx,cx
        jmp dtoc_2bdiv1b_s
       
       
dtoc_2bdiv1b_ok:
        pop si
        pop dx
        pop cx
        pop bx
        pop ax
        ret

code ends
end start

17066038 发表于 2016-8-3 10:49:04

直接套用大规律,即通用性强的处理方法,适应更广阔的条件的方法,可以节省很多繁琐的处理代码

17066038 发表于 2016-8-3 10:51:29

程序的方法很重要,
1、设计好处理时间的逻辑方法、数学解决办法,然后用代码将其逐步实现
2、按此顺序可减少代码的出错,因为很容易漏掉一行应该处理的代码,而使程序处理结果超出想象

17066038 发表于 2016-8-3 11:58:36

17066038 发表于 2016-8-3 10:49
直接套用大规律,即通用性强的处理方法,适应更广阔的条件的方法,可以节省很多繁琐的处理代码

1、被除数为16位,除数为8位,直接按照32位/16位,肯定不会溢出,因为商不会超出16位
2、被除数为32位是,8086cpu为16位,就无法进行扩充为64/32的做法了,需要用到divdw的子程序了
页: [1]
查看完整版本: 汇编语言-实验十-屏幕显示12666