GUNDAM_00 发表于 2024-8-10 17:47:48

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

这个是我的答案:发生了死循环{:5_100:}
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,;年份
       mov dx,
       mov es:,ax
       mov es:,dx;输入年份

      

       mov ax,;工资
       mov dx,
       mov es:,ax
       mov es:,dx

       div word ptr ds:
       mov word ptr es:,ax

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


这个是参考答案:正常运行{:5_99:}
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,

        mov es:,ax

        mov ax,.2

        mov es:.2,ax


        mov ax,.84

        mov es:.5,ax

        mov dx,.86

        mov es:.7,dx


        div word ptr ds:.168

        mov es:.13,ax

       

        mov ax,.168

        mov es:.10,ax


        add di,2

        add bx,4

        add si,16

        loop s


        mov ax,4c00h

        int 21h

code ends

end start

FishC 发表于 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:         ; 读取年份
    mov es:, ax         ; 存储年份
   
    mov ax, ds:       ; 读取工资
    mov es:, ax       ; 存储工资

    mov ax, ds:         ; 读取人数
    mov es:, ax       ; 存储人数

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

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

GUNDAM_00 发表于 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,

        mov es:,ax

        mov ax,.2

        mov es:.2,ax


        mov ax,.84

        mov es:.5,ax

        mov dx,.86

        mov es:.7,dx


        div word ptr ds:.168

        mov es:.13,ax

       

        mov ax,.168

        mov es:.10,ax


        add di,2

        add bx,4

        add si,16

        loop s


        mov ax,4c00h

        int 21h

code ends

end start

GUNDAM_00 发表于 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,

      mov es:,ax

      mov ax,.2

      mov es:.2,ax



      mov ax,.84

      mov es:.5,ax

      mov dx,.86

      mov es:.7,dx



      div word ptr ds:.168

      mov es:.13,ax

      

      mov ax,.168

      mov es:.10,ax



      add di,2

      add bx,4

      add si,16

      loop s



      mov ax,4c00h

      int 21h

code ends

end start

FishC 发表于 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 小助理,如未能正确解答您的问题,请继续追问。

jackz007 发表于 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
. . . . . .

GUNDAM_00 发表于 2024-8-11 10:26:23

jackz007 发表于 2024-8-10 20:39
这里有错误:
dd    345980,590827,803530,1183000,1843000,2759000,3753000.4649000,5937000
   ...

哥们,我终于可以运行了,感谢感谢感谢感谢感谢感谢{:5_110:}{:5_95:}{:5_101:}
页: [1]
查看完整版本: 汇编实验7,关于bx,si,di,选择数据的不同而导致的死循环,不知道如何解决