鱼C论坛

 找回密码
 立即注册
查看: 1909|回复: 5

[汇编作业] 实验10问题3数值显示

[复制链接]
发表于 2018-11-17 17:29:16 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 奥普瓯江 于 2018-11-19 00:24 编辑

这个破问题可是坑哭我了,弄了很久很久,如有什么不对的地方还望指点一二,如果有什么更简单高效的书写方法也请不吝指教谢谢谢谢
assume cs:code, ds:data1, ds:data2, ds:data3

data1 segment
                dw 123, 12666, 1, 8, 3, 38, 0
data1 ends 

data2 segment
                db 10 dup (0)
data2 ends

data3 segment
                db 20 dup (0)
data3 ends

code segment
start:
                mov di, 0
                mov si, 0
one_str:
                mov ax, data1
                mov ds, ax
                mov ax, word ptr ds:[si]
                mov cx, ax
                jcxz one_end
                push si
                
                mov si, 0
                mov bx, data2
                mov ds, bx
                mov bx, data3
                mov es, bx
                call div_str
        
                pop si
                add si, 2
                jmp short one_str
one_end:
                mov dh, 8
                mov dl, 3
                mov cl, 2
                call show_str
                
                mov ax, 4C00H
                int 21H
                
div_str:
                mov dx, 0
                mov bx, 10
                div bx
                add dl, 30H
                mov byte ptr ds:[si], dl
                mov cx, ax
                jcxz div_end
                inc si
                jmp short div_str
div_end:
                mov al, byte ptr ds:[si]
                mov byte ptr es:[di], al
                mov cx, si
                inc di
                jcxz chang_str
                dec si
                jmp short div_end
chang_str:
                mov byte ptr es:[di], 20h
                inc di
                ret
                
show_str:
                dec dh
                mov ax, 0A0H
                mul dh
                mov bx, ax
                
                mov ax, 2
                mul dl
                sub ax, 2
                
                add bx, ax
                
                mov ax, 0b800h
                mov ds, ax
                mov si, 0
                mov di, 0
                mov al, cl
ok:
                mov cl, byte ptr es:[si]
                mov ch, 0
                jcxz good
                mov byte ptr ds:[bx + di], cl
                mov byte ptr ds:[bx + di + 1], al
                inc si
                add di, 2
                jmp short ok
good:        
                ret
                
code ends
end start

以下为我按照我的理解所做的注释
assume cs:code, ds:data1, ds:data2, ds:data3

data1 segment
                dw 123, 12666, 1, 8, 3, 38, 0
data1 ends 

data2 segment
                db 10 dup (0)
data2 ends

data3 segment
                db 20 dup (0)
data3 ends

code segment
start:
                mov di, 0                 ;初始化di寄存器为零
                mov si, 0                 ;初始化si寄存器为零
one_str:
                mov ax, data1             ;把data1数据段的段地址传给ax
                mov ds, ax                ;把ax数据传给ds寄存器,使得数据段可以被调用
                mov ax, word ptr ds:[si]  ;把data1中的两个字节的数据传给ax寄存器
                mov cx, ax                ;把ax中数据传给cx已被jcxz验证
                jcxz one_end              ;判断cx是否为零如果不为零不执行该条语句
                push si                   ;使得si寄存器的数据进入栈中暂时保存,这里要注意栈的调用只能是两个字节也就是十六位数据不能是八位数据
                
                mov si, 0                 ;再次初始化si,这里可以再次调用si是因为si以进栈,在循环重复的时候si将被pop从新赋值所以不影响si的使用
                mov bx, data2             ;把data2数据段的段地址传给bx因为8086中只有ax和bx能被直接赋值,所以他俩需要交替使用,在这里ax以被使用所以就调用bx使他间接赋值给ds
                mov ds, bx                ;把bx中的数据传给ds,因为这个循环是从one_str开始的所以从新付给ds数据并不冲突
                mov bx, data3             ;把data3的值付给bx
                mov es, bx                ;把bx数据传给es使得可以向data3数据段中读取写入数据
                call div_str              ;跳转到div_str标记处
        
                pop si                    ;把si的数值从栈中取回,并在此赋给si
                add si, 2                 ;data1中的si加2
                jmp short one_str         ;无条件跳转回one_str,该程序一共需要循环6次,因为data1中有六组word数据第七组是0
one_end:                          ;上面的循环执行完毕后跳转到该处向下执行上面数据转换和排序等执行完毕后,以下的数据就是显示数据
                mov dh, 8                 ;把他显示在第八行          
                mov dl, 3                 ;第三列这个地方
                mov cl, 2                 ;显示是字体所呈现的属性,绿字
                call show_str             ;跳转到字符标记处show_str:,当遇到ret这条语句就跳转回来,并继续向下执行
                
                mov ax, 4C00H             ;结束语句
                int 21H                   ;结束语句
                
div_str:                          ;16进制数转换成10进制的方法是用10除以16进制数每次的余数就是十进制数的一个元素,直到被除数为0结束
                mov dx, 0                 ;初始dx寄存器数据,这里初始dx主要是为了div运算如果不初始化div运算就会报错
                mov bx, 10                ;初始bx中的数据为10
                div bx                    ;执行除法运算,被除数高位存放在dx中低位存放在了ax中,除数存放在了bx中,商存放在ax中余数存放在dx中
                add dl, 30H               ;给余数加30h因为在ascii码中1的代码是31剩下的以此类推
                mov byte ptr ds:[si], dl  ;把加30h后的余数传到data2中暂时储存
                mov cx, ax                ;把被除数的数据传给cx
                jcxz div_end              ;如果cx中的数据是0那么执行本条语句,跳转到div_end标记处,如果cx中的数据不是0那么什么也不做继续执行下一条语句
                inc si                    ;使得si自动加1
                jmp short div_str         ;无条件跳转到div_str标记处,jmp与jcxz是搭配使用的jcxz是他的结束条件
div_end:                          ;下列语句主要是把顺序倒了的数据调转过来并传到data3数据段
                mov al, byte ptr ds:[si]  ;把data2中本次本次循环si这个字节传给al八位寄存器
                mov byte ptr es:[di], al  ;al八位寄存器中的数据传给data3这个数据段偏移地址di这个位置
                mov cx, si                ;把si中的数据传给cx
                inc di                    ;di自动加1
                jcxz chang_str            ;当cx中的数据为0的时候跳转到chang_str这个标记位置,如果cx中的数据不是0就什么也不做继续执行下一条语句
                dec si                    ;si 自动减1
                jmp short div_end         ;无条件跳转回div_end
chang_str:
                mov byte ptr es:[di], 20h ;给米格段后面加上一个空格
                inc di                    ;di自动加一
                ret                       ;返回call div_str向下执行
                
show_str:
                dec dh                    ;先让行数自动减一因为计算机是从0开始计算的,8行计算机计算的时候是从0开始的到7
                mov ax, 0A0H              ;因为每一行是160个字节换算成16进制就是A0H,把被乘数赋给ax因为mul计算的时候是用ax乘一个寄存器或者内存单元
                mul dh                    ;乘法运算,最后乘积保存在ax中
                mov bx, ax                ;把ax传给bx暂时保存,因为我们还有第二个乘法需要使用到ax寄存器
                
                mov ax, 2                 ;第二个乘法被乘数传给ax
                mul dl                    ;乘法运算,乘积传给ax,3列每一列时2个字节一个字所以这里乘以2
                sub ax, 2                 ;乘积减2这里的减2是因为计算机是从0开始运算的所以上面那三个列是从0开始的也就是0到2,这所说的列是一字为单位的不是以字节所以上面乘以2
                
                add bx, ax                ;用行数字节数加上列数字节数最后定位到的就是我们要在屏幕那个地方输出,最后数据传输给bx
                
                mov ax, 0b800h            ;把0B800H这个段地址传给ax
                mov ds, ax                ;把ax中的数据传给ds使得他可以被读写
                mov si, 0                 ;初始化si寄存器为零
                mov di, 0                 ;初始化di寄存器为零
                mov al, cl                ;把cl中字体的属性参数传给al因为我们下面要调用cl
ok:
                mov cl, byte ptr es:[si]  ;把data3中si位置的数据传给cl中,这样可以及可以传输数据也可以有做下面的jcxz做判断是否跳转,因为汇编规定,内存段中不能相互传输数据,必须得借助寄存器
                mov ch, 0                 ;初始化ch防止ch中有数据
                jcxz good                 ;如果cx中数据是0及执行该条语句跳转到good标记处,如果不是0就不执行该语句
                mov byte ptr ds:[bx + di], cl  ;把cl中的数据传给显示段地址0B800H偏移地址bx+di处
                mov byte ptr ds:[bx + di + 1], al  ;把属性传给段地址0B800H偏移地址bx+di+1处
                inc si                    ;si+1
                add di, 2                 ;di+2因为显示段一次性是输入两个字节的数据所以di+2
                jmp short ok              ;跳转回ok标记处继续执行输出
good:                                  ;如果jcxz good处检测到cx寄存器的数据是0就跳转到该处,并向下执行
                ret                       ;返回call show_str处并向下执行结束语句
                
code ends
end start
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-11-17 22:17:41 | 显示全部楼层
首先,这是你的代码运行的结果,有什么问题吗?
1.png

然后,我写了一个给你参考
assume cs:code, ds:data, ss:stack
data segment
data_arr        dw 123, 12666, 1, 8, 3, 38, 0
buffer                db 512 dup(0)
data ends
stack segment
        db 512 dup(0)
stack ends
code segment
; void NumberToString(uint16_t number, char *buffer);
NumberToString:
        push        bp
        mov        bp, sp
        push        bx
        push        si
        push        di
        
        mov        di, [bp + 6]        ; buffer
        mov        ax, [bp + 4]        ; number
        xor        dx, dx
        mov        cx, 10
@@:
        div        cx
        add        dx, '0'
        mov        [di], dl
        inc        di
        xor        dx, dx
        cmp        ax, 0
        jne        @B
        mov        byte ptr [di], 0        ; '\0'
        
        ; 下面翻转字符串
        dec        di
        mov        si, [bp + 6]        ; buffer
@@:
        cmp        si, di
        jge        @F
        mov        ah, [si]
        mov        al, [di]
        mov        [si], al
        mov        [di], ah
        inc        si
        dec        di
        jmp        @B
@@:
        pop        di
        pop        si
        pop        bx
        mov        sp, bp
        pop        bp
        ret

; void ShowString(uint8_t x, uint8_t y, char *str, uint8_t attr);
ShowString:
        push        bp
        mov        bp, sp
        push        bx
        push        si
        push        di
        push        es
        
        mov        ax, 0b800h
        mov        es, ax
        mov        dl, [bp + 6]        ; y
        mov        al, 160
        mul        dl
        mov        di, ax
        mov        dl, [bp + 4]        ; x
        mov        al, 2
        mul        dl
        add        di, ax
        
        mov        ah, [bp + 10]        ; attr
        mov        si, [bp + 8]        ; str
@@:
        mov        al, [si]
        cmp        al, 0
        je        @F
        mov        es:[di], ax
        inc        si
        add        di, 2
        jmp        @B
@@:
        pop        es
        pop        di
        pop        si
        pop        bx
        mov        sp, bp
        pop        bp
        ret

start:
        mov        ax, stack
        mov        ss, ax
        mov        sp, 512
        mov        ax, data
        mov        ds, ax
        
        mov        si, offset data_arr
        xor        bx, bx
@@:
        cmp        word ptr [si], 0
        je        @F
        mov        ax, offset buffer
        push        ax
        push        [si]
        call        NumberToString
        add        sp, 4
        
        mov        ax, 07h
        push        ax
        mov        ax, offset buffer
        push        ax
        push        bx
        mov        ax, 0
        push        ax
        call        ShowString
        add        sp, 8
        
        add        si, 2
        inc        bx
        jmp        @B
@@:
        mov        ax, 4c00h
        int        21h
code ends
end start
2.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-11-17 22:19:52 | 显示全部楼层
上面的对齐有问题,我这边是对齐的
3.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-11-17 22:20:32 | 显示全部楼层
main.zip (812 Bytes, 下载次数: 1)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-18 10:54:23 | 显示全部楼层
人造人 发表于 2018-11-17 22:17
首先,这是你的代码运行的结果,有什么问题吗?

谢谢,我研究研究吧因为你给的那个程序有好的语句我还没有学到比如说cmp、jmp @B、xor、je等这些我都还不会,所以你这个程序我也是看的一知半解没全看懂,我先往下学也许以后会看懂的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-11-18 11:47:34 | 显示全部楼层
奥普瓯江 发表于 2018-11-18 10:54
谢谢,我研究研究吧因为你给的那个程序有好的语句我还没有学到比如说cmp、jmp @B、xor、je等这些我都还不 ...

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-24 11:26

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表