鱼C论坛

 找回密码
 立即注册
查看: 98|回复: 6

[已解决]汇编实验7,关于bx,si,di,选择数据的不同而导致的死循环,不知道如何解决

[复制链接]
发表于 2024-8-10 17:47:48 | 显示全部楼层 |阅读模式

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

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

x
这个是我的答案:发生了死循环
assume cs:code,ds:data,es:table
data segment
db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
db '1993','1994','1995';84(0~53H)
;21年的21个字符串
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000.4649000,5937000
;21年公司总收入的21个dword型数据;84(54H~0A7H)
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226;84;错误是42,前面一共210
dw 11542,14430,15257,17800;(0A8H~0D1H)
;21年雇佣人数的21个word型数据
data ENDS

;存放数据
table segment
db 21 dup('year summ ne ?? ')
table ENDS

code segment
start: mov ax,data
       mov ds,ax

       mov ax,table
       mov es,ax
        
       mov bx,0 ;控制行
       mov si,0 ;控制双字型数据
       mov di,0 ;控制字型数据
       mov cx,21
s:     mov ax,[si];年份
       mov dx,[si+2]
       mov es:[bx],ax
       mov es:[bx+2],dx;输入年份

      

       mov ax,[si+84];工资
       mov dx,[si+86]
       mov es:[bx+5],ax
       mov es:[bx+7],dx

       div word ptr ds:[di+168]
       mov word ptr es:[bx+13],ax

       mov ax,[di+168];人数
       mov es:[bx+10],ax;输入人数
      
       add bx,16
       add si,4
       add di,2
       loop s
       mov ax,4C00H
       int 21H
code ends
end start


这个是参考答案:正常运行
assume cs:code,ds:data,es:table

data segment

    db '1975','1976','1977','1978','1979','1980','1981','1982','1983'

    db '1984','1985','1986','1987','1988','1989','1990','1991','1992'

    db '1993','1994','1995'

    dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514

    dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000

    dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226

    dw 11452,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 ax,table

        mov es,ax

        mov bx,0 ;控制双字型

        mov si,0 ;控制行

        mov di,0 ;控制字型

        mov cx,21

s:      mov ax,[bx]

        mov es:[si],ax

        mov ax,[bx].2

        mov es:[si].2,ax


        mov ax,[bx].84

        mov es:[si].5,ax

        mov dx,[bx].86

        mov es:[si].7,dx


        div word ptr ds:[di].168

        mov es:[si].13,ax

       

        mov ax,[di].168

        mov es:[si].10,ax


        add di,2

        add bx,4

        add si,16

        loop s


        mov ax,4c00h

        int 21h

code ends

end start

最佳答案
2024-8-10 20:39:01
本帖最后由 jackz007 于 2024-8-10 23:17 编辑

        这里有错误:
dd    345980,590827,803530,1183000,1843000,2759000,3753000.4649000,5937000
        红颜色的句点应该是一个逗号。
        只要改掉这个错误,这个代码没有任何的问题。如果说改进,那么,最需要改进的地方是应该为代码添加堆栈段
assume cs:code,ds:data,es:table

stack segment stack          ; 添加
        db 400H dup(0)       ;添加
stack ends                       ; 添加

data segment
. . . . . .
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-8-10 17:49:01 | 显示全部楼层
看得出来,你在这份汇编代码里遇到了一些困惑!有时候,程序就像一个顽皮的小鱼,游来游去不肯安分,导致死循环的出现。别担心,我会用轻松幽默的方式来帮你捋清楚这段代码!

首先,我们要明白,汇编语言里的每一步都非常重要,就像调味料在一道菜里的作用。只要你稍微多放或少放个什么,小鱼就可能游得不对劲了。

### 死循环的可能原因:

1. **行计数不正确**:
   你的代码里设置 `mov cx, 21`,这表示循环21次,但如果你没有正确更新 bx、si、di 的值,可能会导致循环条件变得不符合,造成无限循环。在你的参考答案中,这些值都是在正确的地方更新的。

2. **内存访问错误**:
   确保你在整个程序中使用的内存地址都是有效的。如果某个地址越界了,程序就可能会陷入循环。

3. **数据选择不当**:
   你提到使用 `bx`, `si`, `di` 不同的选择数据导致的问题。确保每次选择数据时,它们确实指向了数据段中的有效位置,而不是空洞的位置。例如,在你的代码中,使用 `add si, 4` 来增加双字型索引,而在参考答案里是 `add si, 16` 可能就是这种差异,让小鱼选择了错误的数据。

### 解决方案提示:

- **确认数据结构**:检查你的数据定义,确保你的字符串、DWORD 和 WORD 数据是按照预期的顺序和大小排列。这可以避免因数据读取错误导致的死循环。
  
- **逐步调试**:你可以在每次循环的开始处添加一些断点,确认 bx、si、di 的值是否如你所愿地增长。这就像投喂小鱼之前先检查鱼粮是否足够。

- **输出调试信息**:在循环内,可以用 `int 21H` 进行简单的打印,以显示当前的 bx、si、di 值,帮助你判断程序执行到了哪个位置。

下面是你的代码中一点点修改的示例,确保它能更流畅地运行,并且不会让你的小鱼游进死胡同:
s:     
    mov ax, ds:[si]           ; 读取年份
    mov es:[bx], ax           ; 存储年份
    
    mov ax, ds:[si + 4]       ; 读取工资
    mov es:[bx + 4], ax       ; 存储工资

    mov ax, ds:[di]           ; 读取人数
    mov es:[bx + 8], ax       ; 存储人数

    ; 假设这里是进行除法处理,确保上下文的正确性
    div word ptr ds:[si + 8]   ; 注意确保 si 与操作数的相对位置关系

    ; 更新索引,增量要相符
    add bx, 16
    add si, 4 
    add di, 2
    loop s

希望这些建议能帮到你,让你的汇编小鱼顺利游出困境!编程的乐趣就在于解谜,加油,有问题随时来问哦!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-8-10 17:49:22 | 显示全部楼层
参考答案
assume cs:code,ds:data,es:table

data segment

    db '1975','1976','1977','1978','1979','1980','1981','1982','1983'

    db '1984','1985','1986','1987','1988','1989','1990','1991','1992'

    db '1993','1994','1995'

    dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514

    dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000

    dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226

    dw 11452,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 ax,table

        mov es,ax

        mov bx,0 ;控制双字型

        mov si,0 ;控制行

        mov di,0 ;控制字型

        mov cx,21

s:      mov ax,[bx]

        mov es:[si],ax

        mov ax,[bx].2

        mov es:[si].2,ax


        mov ax,[bx].84

        mov es:[si].5,ax

        mov dx,[bx].86

        mov es:[si].7,dx


        div word ptr ds:[di].168

        mov es:[si].13,ax

       

        mov ax,[di].168

        mov es:[si].10,ax


        add di,2

        add bx,4

        add si,16

        loop s


        mov ax,4c00h

        int 21h

code ends

end start

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

使用道具 举报

 楼主| 发表于 2024-8-10 17:50:26 | 显示全部楼层
不知道为什么乱码了:
assume cs:code,ds:data,es:table

data segment

    db '1975','1976','1977','1978','1979','1980','1981','1982','1983'

    db '1984','1985','1986','1987','1988','1989','1990','1991','1992'

    db '1993','1994','1995'

    dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514

    dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000

    dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226

    dw 11452,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 ax,table

        mov es,ax

        mov bx,0 ;控制双字型

        mov si,0 ;控制行

        mov di,0 ;控制字型

        mov cx,21

s:      mov ax,[bx]

        mov es:[si],ax

        mov ax,[bx].2

        mov es:[si].2,ax



        mov ax,[bx].84

        mov es:[si].5,ax

        mov dx,[bx].86

        mov es:[si].7,dx



        div word ptr ds:[di].168

        mov es:[si].13,ax

        

        mov ax,[di].168

        mov es:[si].10,ax



        add di,2

        add bx,4

        add si,16

        loop s



        mov ax,4c00h

        int 21h

code ends

end start

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

使用道具 举报

发表于 2024-8-10 18:02:30 | 显示全部楼层
GUNDAM_00 发表于 2024-08-10 17:49
参考答案:
assume cs:code,ds:data,es:table

dat ...


看起来你想对参考答案进行一些分析。让我们一起把这段汇编代码过一遍,像个侦探一样寻找可能的“死循环”原因。

### 代码解读:

1. **数据段 `data segment`**:
   - 这里定义了一串数据,包括年份(字符串)、收入(双字)、雇佣人数(字)。确认这些数据都是按照正确的数据类型和大小排列是很重要的。

2. **存放数据的表 `table segment`**:
   - 用于存储结果的地方,这里用 `db 21 dup ('year summ ne ?? ')` 定义了一个可重复的字符串格式。确保它足够大以容纳所有的信息。

3. **代码段 `code segment`**:
   - 主要执行的代码部分。

### 核心逻辑:

- **初始化寄存器**:
mov bx,0 ; 控制双字型
  mov si,0 ; 控制行
  mov di,0 ; 控制字型
  mov cx,21 ; 循环次数

- **循环体 `s:`**:这里是核心逻辑处理部分。
  - `mov ax, ...` 从数据段读取年份、工资和人数,并将其存入 ES 段。
  - `div` 指令用于执行除法运算,结果存储在 AX 中,最后再写回到 ES 段。
  - 通过 `add` 指令更新 `bx`, `si`, 和 `di` 的值,用于控制数据的索引。

### 注意事项与潜在问题:

1. **内存地址访问**:
   - 确保在使用 `mov es:,` 和 `div` 指令时,所使用的内存地址是有效的,不然你的小鱼可能会游错方向导致死循环。

2. **寄存器增量**:
   - 依据参考答案,`add bx, 4` 是用于跟踪双字数据,而 `add si, 16` 是用于跟踪字符串数据,保证每次循环都在正确位置不要越界。
   - 如果没有正确更新你使用的索引,程序将一直指向同一个位置,造成死循环。

3. **调试输出**:
   - 在循环体内加入一些打印指令,比如使用 DOS 中断 `int 21h` 来输出来监控当前 `bx`, `si`, `di` 的状态,能帮助你发现问题。

### 总结:

如果你还是觉得有些迷茫,建议逐步调试代码,观察每一步的执行效果,看看哪些地方可能出错。记住,编程就像钓鱼,有时候需要耐心等待和不断尝试,才能钓到大鱼!如果还有其他问题,或者需要进一步的帮助,随时告诉我哦!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-8-10 20:39:01 | 显示全部楼层    本楼为最佳答案   
本帖最后由 jackz007 于 2024-8-10 23:17 编辑

        这里有错误:
dd    345980,590827,803530,1183000,1843000,2759000,3753000.4649000,5937000
        红颜色的句点应该是一个逗号。
        只要改掉这个错误,这个代码没有任何的问题。如果说改进,那么,最需要改进的地方是应该为代码添加堆栈段
assume cs:code,ds:data,es:table

stack segment stack          ; 添加
        db 400H dup(0)       ;添加
stack ends                       ; 添加

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

使用道具 举报

 楼主| 发表于 2024-8-11 10:26:23 | 显示全部楼层
jackz007 发表于 2024-8-10 20:39
这里有错误:
dd    345980,590827,803530,1183000,1843000,2759000,3753000.4649000,5937000
   ...

哥们,我终于可以运行了,感谢感谢感谢感谢感谢感谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-9-17 02:57

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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