鱼C论坛

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

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

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

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

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

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

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

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

  5. data2 segment
  6.                 db 10 dup (0)
  7. data2 ends

  8. data3 segment
  9.                 db 20 dup (0)
  10. data3 ends

  11. code segment
  12. start:
  13.                 mov di, 0
  14.                 mov si, 0
  15. one_str:
  16.                 mov ax, data1
  17.                 mov ds, ax
  18.                 mov ax, word ptr ds:[si]
  19.                 mov cx, ax
  20.                 jcxz one_end
  21.                 push si
  22.                
  23.                 mov si, 0
  24.                 mov bx, data2
  25.                 mov ds, bx
  26.                 mov bx, data3
  27.                 mov es, bx
  28.                 call div_str
  29.        
  30.                 pop si
  31.                 add si, 2
  32.                 jmp short one_str
  33. one_end:
  34.                 mov dh, 8
  35.                 mov dl, 3
  36.                 mov cl, 2
  37.                 call show_str
  38.                
  39.                 mov ax, 4C00H
  40.                 int 21H
  41.                
  42. div_str:
  43.                 mov dx, 0
  44.                 mov bx, 10
  45.                 div bx
  46.                 add dl, 30H
  47.                 mov byte ptr ds:[si], dl
  48.                 mov cx, ax
  49.                 jcxz div_end
  50.                 inc si
  51.                 jmp short div_str
  52. div_end:
  53.                 mov al, byte ptr ds:[si]
  54.                 mov byte ptr es:[di], al
  55.                 mov cx, si
  56.                 inc di
  57.                 jcxz chang_str
  58.                 dec si
  59.                 jmp short div_end
  60. chang_str:
  61.                 mov byte ptr es:[di], 20h
  62.                 inc di
  63.                 ret
  64.                
  65. show_str:
  66.                 dec dh
  67.                 mov ax, 0A0H
  68.                 mul dh
  69.                 mov bx, ax
  70.                
  71.                 mov ax, 2
  72.                 mul dl
  73.                 sub ax, 2
  74.                
  75.                 add bx, ax
  76.                
  77.                 mov ax, 0b800h
  78.                 mov ds, ax
  79.                 mov si, 0
  80.                 mov di, 0
  81.                 mov al, cl
  82. ok:
  83.                 mov cl, byte ptr es:[si]
  84.                 mov ch, 0
  85.                 jcxz good
  86.                 mov byte ptr ds:[bx + di], cl
  87.                 mov byte ptr ds:[bx + di + 1], al
  88.                 inc si
  89.                 add di, 2
  90.                 jmp short ok
  91. good:       
  92.                 ret
  93.                
  94. code ends
  95. end start
复制代码


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

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

  5. data2 segment
  6.                 db 10 dup (0)
  7. data2 ends

  8. data3 segment
  9.                 db 20 dup (0)
  10. data3 ends

  11. code segment
  12. start:
  13.                 mov di, 0                 ;初始化di寄存器为零
  14.                 mov si, 0                 ;初始化si寄存器为零
  15. one_str:
  16.                 mov ax, data1             ;把data1数据段的段地址传给ax
  17.                 mov ds, ax                ;把ax数据传给ds寄存器,使得数据段可以被调用
  18.                 mov ax, word ptr ds:[si]  ;把data1中的两个字节的数据传给ax寄存器
  19.                 mov cx, ax                ;把ax中数据传给cx已被jcxz验证
  20.                 jcxz one_end              ;判断cx是否为零如果不为零不执行该条语句
  21.                 push si                   ;使得si寄存器的数据进入栈中暂时保存,这里要注意栈的调用只能是两个字节也就是十六位数据不能是八位数据
  22.                
  23.                 mov si, 0                 ;再次初始化si,这里可以再次调用si是因为si以进栈,在循环重复的时候si将被pop从新赋值所以不影响si的使用
  24.                 mov bx, data2             ;把data2数据段的段地址传给bx因为8086中只有ax和bx能被直接赋值,所以他俩需要交替使用,在这里ax以被使用所以就调用bx使他间接赋值给ds
  25.                 mov ds, bx                ;把bx中的数据传给ds,因为这个循环是从one_str开始的所以从新付给ds数据并不冲突
  26.                 mov bx, data3             ;把data3的值付给bx
  27.                 mov es, bx                ;把bx数据传给es使得可以向data3数据段中读取写入数据
  28.                 call div_str              ;跳转到div_str标记处
  29.        
  30.                 pop si                    ;把si的数值从栈中取回,并在此赋给si
  31.                 add si, 2                 ;data1中的si加2
  32.                 jmp short one_str         ;无条件跳转回one_str,该程序一共需要循环6次,因为data1中有六组word数据第七组是0
  33. one_end:                          ;上面的循环执行完毕后跳转到该处向下执行上面数据转换和排序等执行完毕后,以下的数据就是显示数据
  34.                 mov dh, 8                 ;把他显示在第八行         
  35.                 mov dl, 3                 ;第三列这个地方
  36.                 mov cl, 2                 ;显示是字体所呈现的属性,绿字
  37.                 call show_str             ;跳转到字符标记处show_str:,当遇到ret这条语句就跳转回来,并继续向下执行
  38.                
  39.                 mov ax, 4C00H             ;结束语句
  40.                 int 21H                   ;结束语句
  41.                
  42. div_str:                          ;16进制数转换成10进制的方法是用10除以16进制数每次的余数就是十进制数的一个元素,直到被除数为0结束
  43.                 mov dx, 0                 ;初始dx寄存器数据,这里初始dx主要是为了div运算如果不初始化div运算就会报错
  44.                 mov bx, 10                ;初始bx中的数据为10
  45.                 div bx                    ;执行除法运算,被除数高位存放在dx中低位存放在了ax中,除数存放在了bx中,商存放在ax中余数存放在dx中
  46.                 add dl, 30H               ;给余数加30h因为在ascii码中1的代码是31剩下的以此类推
  47.                 mov byte ptr ds:[si], dl  ;把加30h后的余数传到data2中暂时储存
  48.                 mov cx, ax                ;把被除数的数据传给cx
  49.                 jcxz div_end              ;如果cx中的数据是0那么执行本条语句,跳转到div_end标记处,如果cx中的数据不是0那么什么也不做继续执行下一条语句
  50.                 inc si                    ;使得si自动加1
  51.                 jmp short div_str         ;无条件跳转到div_str标记处,jmp与jcxz是搭配使用的jcxz是他的结束条件
  52. div_end:                          ;下列语句主要是把顺序倒了的数据调转过来并传到data3数据段
  53.                 mov al, byte ptr ds:[si]  ;把data2中本次本次循环si这个字节传给al八位寄存器
  54.                 mov byte ptr es:[di], al  ;al八位寄存器中的数据传给data3这个数据段偏移地址di这个位置
  55.                 mov cx, si                ;把si中的数据传给cx
  56.                 inc di                    ;di自动加1
  57.                 jcxz chang_str            ;当cx中的数据为0的时候跳转到chang_str这个标记位置,如果cx中的数据不是0就什么也不做继续执行下一条语句
  58.                 dec si                    ;si 自动减1
  59.                 jmp short div_end         ;无条件跳转回div_end
  60. chang_str:
  61.                 mov byte ptr es:[di], 20h ;给米格段后面加上一个空格
  62.                 inc di                    ;di自动加一
  63.                 ret                       ;返回call div_str向下执行
  64.                
  65. show_str:
  66.                 dec dh                    ;先让行数自动减一因为计算机是从0开始计算的,8行计算机计算的时候是从0开始的到7
  67.                 mov ax, 0A0H              ;因为每一行是160个字节换算成16进制就是A0H,把被乘数赋给ax因为mul计算的时候是用ax乘一个寄存器或者内存单元
  68.                 mul dh                    ;乘法运算,最后乘积保存在ax中
  69.                 mov bx, ax                ;把ax传给bx暂时保存,因为我们还有第二个乘法需要使用到ax寄存器
  70.                
  71.                 mov ax, 2                 ;第二个乘法被乘数传给ax
  72.                 mul dl                    ;乘法运算,乘积传给ax,3列每一列时2个字节一个字所以这里乘以2
  73.                 sub ax, 2                 ;乘积减2这里的减2是因为计算机是从0开始运算的所以上面那三个列是从0开始的也就是0到2,这所说的列是一字为单位的不是以字节所以上面乘以2
  74.                
  75.                 add bx, ax                ;用行数字节数加上列数字节数最后定位到的就是我们要在屏幕那个地方输出,最后数据传输给bx
  76.                
  77.                 mov ax, 0b800h            ;把0B800H这个段地址传给ax
  78.                 mov ds, ax                ;把ax中的数据传给ds使得他可以被读写
  79.                 mov si, 0                 ;初始化si寄存器为零
  80.                 mov di, 0                 ;初始化di寄存器为零
  81.                 mov al, cl                ;把cl中字体的属性参数传给al因为我们下面要调用cl
  82. ok:
  83.                 mov cl, byte ptr es:[si]  ;把data3中si位置的数据传给cl中,这样可以及可以传输数据也可以有做下面的jcxz做判断是否跳转,因为汇编规定,内存段中不能相互传输数据,必须得借助寄存器
  84.                 mov ch, 0                 ;初始化ch防止ch中有数据
  85.                 jcxz good                 ;如果cx中数据是0及执行该条语句跳转到good标记处,如果不是0就不执行该语句
  86.                 mov byte ptr ds:[bx + di], cl  ;把cl中的数据传给显示段地址0B800H偏移地址bx+di处
  87.                 mov byte ptr ds:[bx + di + 1], al  ;把属性传给段地址0B800H偏移地址bx+di+1处
  88.                 inc si                    ;si+1
  89.                 add di, 2                 ;di+2因为显示段一次性是输入两个字节的数据所以di+2
  90.                 jmp short ok              ;跳转回ok标记处继续执行输出
  91. good:                                  ;如果jcxz good处检测到cx寄存器的数据是0就跳转到该处,并向下执行
  92.                 ret                       ;返回call show_str处并向下执行结束语句
  93.                
  94. code ends
  95. end start
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

然后,我写了一个给你参考
  1. assume cs:code, ds:data, ss:stack
  2. data segment
  3. data_arr        dw 123, 12666, 1, 8, 3, 38, 0
  4. buffer                db 512 dup(0)
  5. data ends
  6. stack segment
  7.         db 512 dup(0)
  8. stack ends
  9. code segment
  10. ; void NumberToString(uint16_t number, char *buffer);
  11. NumberToString:
  12.         push        bp
  13.         mov        bp, sp
  14.         push        bx
  15.         push        si
  16.         push        di
  17.        
  18.         mov        di, [bp + 6]        ; buffer
  19.         mov        ax, [bp + 4]        ; number
  20.         xor        dx, dx
  21.         mov        cx, 10
  22. @@:
  23.         div        cx
  24.         add        dx, '0'
  25.         mov        [di], dl
  26.         inc        di
  27.         xor        dx, dx
  28.         cmp        ax, 0
  29.         jne        @B
  30.         mov        byte ptr [di], 0        ; '\0'
  31.        
  32.         ; 下面翻转字符串
  33.         dec        di
  34.         mov        si, [bp + 6]        ; buffer
  35. @@:
  36.         cmp        si, di
  37.         jge        @F
  38.         mov        ah, [si]
  39.         mov        al, [di]
  40.         mov        [si], al
  41.         mov        [di], ah
  42.         inc        si
  43.         dec        di
  44.         jmp        @B
  45. @@:
  46.         pop        di
  47.         pop        si
  48.         pop        bx
  49.         mov        sp, bp
  50.         pop        bp
  51.         ret

  52. ; void ShowString(uint8_t x, uint8_t y, char *str, uint8_t attr);
  53. ShowString:
  54.         push        bp
  55.         mov        bp, sp
  56.         push        bx
  57.         push        si
  58.         push        di
  59.         push        es
  60.        
  61.         mov        ax, 0b800h
  62.         mov        es, ax
  63.         mov        dl, [bp + 6]        ; y
  64.         mov        al, 160
  65.         mul        dl
  66.         mov        di, ax
  67.         mov        dl, [bp + 4]        ; x
  68.         mov        al, 2
  69.         mul        dl
  70.         add        di, ax
  71.        
  72.         mov        ah, [bp + 10]        ; attr
  73.         mov        si, [bp + 8]        ; str
  74. @@:
  75.         mov        al, [si]
  76.         cmp        al, 0
  77.         je        @F
  78.         mov        es:[di], ax
  79.         inc        si
  80.         add        di, 2
  81.         jmp        @B
  82. @@:
  83.         pop        es
  84.         pop        di
  85.         pop        si
  86.         pop        bx
  87.         mov        sp, bp
  88.         pop        bp
  89.         ret

  90. start:
  91.         mov        ax, stack
  92.         mov        ss, ax
  93.         mov        sp, 512
  94.         mov        ax, data
  95.         mov        ds, ax
  96.        
  97.         mov        si, offset data_arr
  98.         xor        bx, bx
  99. @@:
  100.         cmp        word ptr [si], 0
  101.         je        @F
  102.         mov        ax, offset buffer
  103.         push        ax
  104.         push        [si]
  105.         call        NumberToString
  106.         add        sp, 4
  107.        
  108.         mov        ax, 07h
  109.         push        ax
  110.         mov        ax, offset buffer
  111.         push        ax
  112.         push        bx
  113.         mov        ax, 0
  114.         push        ax
  115.         call        ShowString
  116.         add        sp, 8
  117.        
  118.         add        si, 2
  119.         inc        bx
  120.         jmp        @B
  121. @@:
  122.         mov        ax, 4c00h
  123.         int        21h
  124. code ends
  125. end start
复制代码

2.png
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-11-17 22:19:52 | 显示全部楼层
上面的对齐有问题,我这边是对齐的
3.png
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-11-17 22:20:32 | 显示全部楼层
main.zip (812 Bytes, 下载次数: 1)
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

使用道具 举报

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

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-10 09:33

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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