lyoal 发表于 2012-12-2 01:37:59

一个周了一直在编写10章节的实验子程序,最后一个大牛帮忙看看,在此谢过!

本帖最后由 lyoal 于 2012-12-2 01:37 编辑

这个程序整了两小时写出来了,按自己的思路写的。12666字符串在我的本本上,无论怎么调示都是显示b2666.
但是如果将AX的数据改为32666就能正常显示,求大牛帮忙解释一下,这是为啥类?
请看代码:
assume cs:code,ds:data
data segment
      db 0 dup (0)
data ends

stack segment
      db 50 dup (0)
stack ends

code segment
start:      mov ax,12666                ;定义一个数据,用于将数据转化成字符串显示出来
                mov bx,data
                mov ds,bx                        ;关联数据段
                mov bx,stack
                mov ss,bx
                mov sp,50
               
                mov bx,0                        ;用来计数
               
                call cstr
               
                mov dh,8                        ;定义字符串在显卡中的定位,第8行
                mov dl,11                        ;第3列
                mov cl,0cah                        ;颜色值
               
                call show_str
               
                mov ax,4c00h
                int 21h
               
               
               
cstr:      push ax                              ;将需要用到的寄存器的原始数据入栈
                push bx
                push cx
                push si
                push di
                push dx



cstr1:      ;mov cx,0
                mov cx,10d                        ;定义一个十进制数据的10,用作除数与被除数12666进行运算,方法是取余法
                mov dx,0                        ;先将用于存放余数的寄存器DX置0
                div cx                              ;AX/CX(为什么除数为AL时会溢出呢?)
               
                mov cx,ax                         ;将余数送入CX中,用判断余数是否为0,当余数为0时,表示被除数被除尽,则进行跳转(将商为0作为判断条件)
                jcxz loops
               
                add dx,30h                        ;将余数转化为ASCII码字符
                push dx                         ;暂将转换成的字符压入栈中
                inc bx
                loop cstr1
               
               
loops:      add dx,30h                        ;因为余数为0条件成立后,最后一位字符未被进行转换,这里对其进行转换并入栈
                push dx
                inc bx
               
                mov cx,bx                        ;将计数器中的数据传送给CX用于循环,将栈中的字符依次送入数据段DS中
                mov si,0                        ;索引DS数据段中的位置或着说是用于定位
               

s:                pop ax
                mov ,al                        ;将出栈的字符送入到数据段DS中去
                inc si
                loop s
               
               
ok:                pop dx                              ;数据处理完成后,将原始数据出栈
                pop di
                pop si
                pop cx
                pop bx
                pop ax
                ret                                        ;返回
               
               
               
show_str:      push ax                        ;寄存器原始数据入栈
                        push bx
                        push cx
                        push dx
                        push si
                        push di
                        
                        mov ax,0b800h
                        mov es,ax                ;将显存的段地址关联给ES段寄存器
                        
                        dec dh
                        mov ax,0                ;谨慎一点将AX寄存器置0一下
                        mov bx,0
                        mov ax,0a0h                ;将显存中一行的字节数的宽度给AX
                        mul dh                        ;现在AX中存放的就是显存中前7行的偏移地址
                        mov bx,ax                ;将结果送入DX寄存器存放,AX接下来用于计算列的偏移地址
                        
                        mov ax,0
                        dec dl                        ;曾经让我纠结的地方,因80个字符位置,每一个字符位包含一个字节给数据,一个字节给颜色。所以两列四字节才能显示一个带有颜色的字符,显示一个完整字符
                                                      ;必须将字符放在偶数位,颜色放在奇数位,故减去一列
                        mul dl
                        add bx,ax                ;至此,DX寄存器中存放着显存的前8行第2列的偏移地址
                        
                        mov ch,0                ;目的是用于判断CX寄存器是否为0
                        mov al,cl                ;将CL寄存器中的颜色送入到AL中
                        mov si,0
                        mov di,0
                        
s1:                        mov cl,
                        jcxz okey                ;当CX为0时跳转返回
                        mov byte ptr es:,cl
                        mov byte ptr es:,al
                        inc si
                        add di,2
                        loop s1
                        
                        
okey:                pop di
                        pop si
                        pop dx
                        pop cx
                        pop bx
                        pop ax
                        ret
                        
                        code ends
end start

s0512 发表于 2012-12-2 01:38:00

assume cs:code,ds:data
data segment
      db 0 dup (0)
data ends
stack segment
      db 50 dup (0)
stack ends
code segment
start:      mov ax,12666                ;定义一个数据,用于将数据转化成字符串显示出来
                mov bx,data
                mov ds,bx                        ;关联数据段
                mov bx,stack
                mov ss,bx
                mov sp,50
               
                mov bx,0                        ;用来计数
               
                call cstr
               
                mov dh,8                        ;定义字符串在显卡中的定位,第8行
                mov dl,11                        ;第3列
                mov cl,0cah                        ;颜色值
               
                call show_str
               
                mov ax,4c00h
                int 21h
               
               
               
cstr:      push ax                              ;将需要用到的寄存器的原始数据入栈
                push bx
                push cx
                push si
                push di
                push dx

cstr1:      ;mov cx,0
                mov cx,10d                        ;定义一个十进制数据的10,用作除数与被除数12666进行运算,方法是取余法
                mov dx,0                        ;先将用于存放余数的寄存器DX置0
                div cx                              ;AX/CX(为什么除数为AL时会溢出呢?)
               
                ;mov cx,ax                         ;将余数送入CX中,用判断余数是否为0,当余数为0时,表示被除数被除尽,则进行跳转(将商为0作为判断条件)
               
                ;jcxz loops
                add dx,30h                        ;将余数转化为ASCII码字符
                push dx                         ;暂将转换成的字符压入栈中
                inc bx
               
                cmp ax,0
                je loops
                jmp cstr1
               
               
               
loops:       ;add dx,30h                        ;因为余数为0条件成立后,最后一位字符未被进行转换,这里对其进行转换并入栈
               ; push dx
                ;inc bx
               
                mov cx,bx                        ;将计数器中的数据传送给CX用于循环,将栈中的字符依次送入数据段DS中
                mov si,0                        ;索引DS数据段中的位置或着说是用于定位
               
s:                pop ax
                mov ,al                        ;将出栈的字符送入到数据段DS中去
                inc si
                loop s
               
               
ok:                pop dx                              ;数据处理完成后,将原始数据出栈
                pop di
                pop si
                pop cx
                pop bx
                pop ax
                ret                                        ;返回
               
               
               
show_str:      push ax                        ;寄存器原始数据入栈
                        push bx
                        push cx
                        push dx
                        push si
                        push di
                        
                        mov ax,0b800h
                        mov es,ax                ;将显存的段地址关联给ES段寄存器
                        
                        dec dh
                        mov ax,0                ;谨慎一点将AX寄存器置0一下
                        mov bx,0
                        mov ax,0a0h                ;将显存中一行的字节数的宽度给AX
                        mul dh                        ;现在AX中存放的就是显存中前7行的偏移地址
                        mov bx,ax                ;将结果送入DX寄存器存放,AX接下来用于计算列的偏移地址
                        
                        mov ax,0
                        dec dl                        ;曾经让我纠结的地方,因80个字符位置,每一个字符位包含一个字节给数据,一个字节给颜色。所以两列四字节才能显示一个带有颜色的字符,显示一个完整字符
                                                      ;必须将字符放在偶数位,颜色放在奇数位,故减去一列
                        mul dl
                        add bx,ax                ;至此,DX寄存器中存放着显存的前8行第2列的偏移地址
                        
                        mov ch,0                ;目的是用于判断CX寄存器是否为0
                        mov al,cl                ;将CL寄存器中的颜色送入到AL中
                        mov si,0
                        mov di,0
                        
s1:                        mov cl,
                        jcxz okey                ;当CX为0时跳转返回
                        mov byte ptr es:,cl
                        mov byte ptr es:,al
                        inc si
                        add di,2
                        loop s1
                        
                        
okey:                pop di
                        pop si
                        pop dx
                        pop cx
                        pop bx
                        pop ax
                        ret
                        
                        code ends
end start

lyoal 发表于 2012-12-2 10:17:17

s0512 发表于 2012-12-2 10:06 static/image/common/back.gif
assume cs:code,ds:data
data segment
      db 0 dup (0)


大哥,一语惊醒梦中人呢。小弟佩服!

lyoal 发表于 2012-12-2 10:21:06

不过,JE指令小弟还没有学到。标志位还木懂啥意思。我看了您的解答,忽然发现我加了条件判断后又重复使用了loop指令,至使CX值发现变化。我把loop cstr1,改成jmp cstr1,就成功了执行了。非常感谢!

s0512 发表于 2012-12-2 10:43:47

lyoal 发表于 2012-12-2 10:21 static/image/common/back.gif
不过,JE指令小弟还没有学到。标志位还木懂啥意思。我看了您的解答,忽然发现我加了条件判断后又重复使用了 ...

一起加油!!!
页: [1]
查看完整版本: 一个周了一直在编写10章节的实验子程序,最后一个大牛帮忙看看,在此谢过!