鱼C论坛

 找回密码
 立即注册
查看: 1369|回复: 3

[已解决]汇编实验7,死循环,debug只显示年份,整一天了,不知道哪出错了,求指点

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

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

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

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,[di+168];人数
       mov es:[bx+10],ax

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

       div word ptr es:[bx+10]
       mov es:[bx+13],ax
       add bx,16
       add si,4
       add di,2
       loop s
       mov ax,2C00H
       int 21H
code ends
end start
最佳答案
2024-8-7 18:24:04
1.
  1. 从您提供的代码和描述中,我可以看到几个潜在的问题点,这些问题可能导致程序陷入死循环或者不能正确执行。下面是逐一分析和建议的修改:

  2. 数据读取错误:
  3. 您的代码中使用了 mov ax,[si] 来读取年份,但实际上您的年份数据是以字节(byte)形式存储的,而不是字(word)。因此,您应该使用 mov al,[si] 来读取一个字节到 AL 寄存器,并使用 mov ah,0 来确保 AH 为0(如果您的年份都是两位数的话)。然后,您可以考虑如何存储这个年份(比如,直接存储到 ES:[BX] 的位置,或者将其转换为字符形式存储)。
  4. 数据偏移量计算:
  5. 您在计算收入和雇佣人数的偏移量时使用了固定的偏移量(如 [di+168] 和 [si+84]),但这看起来并不正确。这些偏移量应该基于 BX 或 SI 的当前值动态计算,特别是如果您希望按照年份的顺序来访问这些数据。
  6. 循环控制:
  7. 您使用了 loop s 指令,但没有设置循环计数器(CX)。在 s 标签之前,您已经设置了 CX 为 21,这是正确的,但请确保在 loop 指令执行之前 CX 的值没有被意外修改。
  8. 除法操作:
  9. 您在使用 div 指令进行除法运算时,必须确保除数(这里是 es:[bx+10])不为零,否则会导致除零错误。您可能需要在执行除法之前检查除数是否为零。
  10. 字符存储:
  11. 如果您希望将年份、收入和雇佣人数转换为字符串形式存储在 table 段中,您需要编写额外的代码来处理这种转换。
  12. 下面是一个简化的示例,仅展示如何正确读取年份并存储到 table 段中(注意,这里未处理其他数据和转换):

  13. asm
  14. assume cs:code, ds:data, es:table  
  15.   
  16. data segment  
  17.     db '1975', '1976', ... ; 年份数据  
  18. data ends  
  19.   
  20. table segment  
  21.     db 21 dup('????') ; 预留空间存储年份字符串  
  22. table ends  
  23.   
  24. code segment  
  25. start:  
  26.     mov ax, data  
  27.     mov ds, ax  
  28.   
  29.     mov ax, table  
  30.     mov es, ax  
  31.   
  32.     mov bx, 0      ; ES:BX 指向 table 段  
  33.     mov cx, 21     ; 循环次数  
  34.     mov si, 0      ; DS:SI 指向年份数据  
  35.   
  36. s:  mov al, [si]   ; 读取年份的第一个字节  
  37.     mov es:[bx], al  
  38.     inc si  
  39.   
  40.     mov al, [si]   ; 读取年份的第二个字节  
  41.     mov es:[bx+1], al  
  42.     inc si  
  43.   
  44.     add bx, 2      ; 移动到 table 段的下一个位置  
  45.     loop s  
  46.   
  47.     mov ax, 4C00H  ; 退出到 DOS  
  48.     int 21H  
  49. code ends  
  50. end start
  51. 请注意,这个示例仅处理年份的读取和存储,未涉及其他数据的处理。您需要根据实际需求进一步扩展和修改代码。
复制代码

2.
  1. assume cs:code, ds:data, es:table
  2. data segment
  3. years db '1975','1976','1977',... ; 继续到1995
  4. incomes dd 16,22,...; 收入数据
  5. employees dw 3,7,...; 人员数据
  6. data ends

  7. table segment
  8. db 21 dup('year summ ne ?? ')
  9. table ends

  10. code segment
  11. start:
  12.     mov ax, data
  13.     mov ds, ax

  14.     mov ax, table
  15.     mov es, ax
  16.    
  17.     mov cx, 21          ; 设置循环次数为21
  18.     xor bx, bx          ; bx 用于存储偏移量,初始为0
  19.     xor si, si          ; si 用于年数据偏移
  20.     xor di, di          ; di 用于人员数据偏移

  21. s:
  22.     ; 读取年份
  23.     mov al, [years + si]  ; 读取年份
  24.     mov [es:bx], al       ; 存入 table
  25.     inc si                 ; 移动到下一个年份
  26.     add bx, 16             ; 更新表格位置

  27.     ; 读取人数
  28.     mov ax, [employees + di]
  29.     mov [es:bx], ax
  30.     add di, 2              ; 更新偏移
  31.     add bx, 2              ; 更新表格位置

  32.     ; 读取收入
  33.     mov eax, [incomes + si]
  34.     ; 修改计算逻辑,根据需要进行计算

  35.     ; 检查循环是否完成
  36.     loop s                 ; 如果 cx 不为0,则继续循环

  37.     ; 程序结束
  38.     mov ax, 2C00H
  39.     int 21H

  40. code ends
  41. end start
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-8-7 17:23:01 | 显示全部楼层
看起来你的汇编代码让你陷入了一个死循环,别担心,我们来一起看看问题出在哪里。首先,我们需要确保代码逻辑清晰,避免在循环中没完没了地转圈。

从你提供的代码来看,有几个地方可能会导致问题:

1. **数据段定义错误**:你表示年份、人数和工资的方式可能有误。`mov ax,;年份`、`mov ax,;人数` 和 `mov ax,;工资` 这些行没有正确加载数据。你需要指定数据段中的具体位置,比如使用 `mov ax, [data segment]` 这样的形式来获取具体的数据。

2. **移动数据的方式**:在以下几行中:
  
  1. mov es:,ax
  2.    mov es:,dx
复制代码

   这里应该是把数据存储到 `table` 段中,而不是简单地使用 `es` 段。不然程序将无法找到你想要输出的内容。

3. **循环计数器控制**:你用 `loop s` 来控制循环,但注意一定要确保 `cx` 的值能正确地减少到零。如果在循环中没有修改 `cx`,这个循环将永远不会结束。

4. **整合代码**:整理一下代码结构,便于代码的理解和调试。记得每当你修改数据段 (如 `si`, `di`, `bx`) 后,一定要注意它们目标地址是否合理。

下面是一个修正后的代码示例(注意这里是伪代码,可能需要根据你的具体需求进行调整):

  1. assume cs:code, ds:data, es:table
  2. data segment
  3. years db '1975','1976','1977',... ; 继续到1995
  4. incomes dd 16,22,...; 收入数据
  5. employees dw 3,7,...; 人员数据
  6. data ends

  7. table segment
  8. db 21 dup('year summ ne ?? ')
  9. table ends

  10. code segment
  11. start:
  12.     mov ax, data
  13.     mov ds, ax

  14.     mov ax, table
  15.     mov es, ax
  16.    
  17.     mov cx, 21          ; 设置循环次数为21
  18.     xor bx, bx          ; bx 用于存储偏移量,初始为0
  19.     xor si, si          ; si 用于年数据偏移
  20.     xor di, di          ; di 用于人员数据偏移

  21. s:
  22.     ; 读取年份
  23.     mov al, [years + si]  ; 读取年份
  24.     mov [es:bx], al       ; 存入 table
  25.     inc si                 ; 移动到下一个年份
  26.     add bx, 16             ; 更新表格位置

  27.     ; 读取人数
  28.     mov ax, [employees + di]
  29.     mov [es:bx], ax
  30.     add di, 2              ; 更新偏移
  31.     add bx, 2              ; 更新表格位置

  32.     ; 读取收入
  33.     mov eax, [incomes + si]
  34.     ; 修改计算逻辑,根据需要进行计算

  35.     ; 检查循环是否完成
  36.     loop s                 ; 如果 cx 不为0,则继续循环

  37.     ; 程序结束
  38.     mov ax, 2C00H
  39.     int 21H

  40. code ends
  41. end start
复制代码


这段代码进行了基本的结构调整以帮助你更易懂,也记得添加适时的注释。希望这可以帮助你找到并解决问题!如果还有其他疑问,毫不犹豫地问我吧!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-8-7 18:24:04 | 显示全部楼层    本楼为最佳答案   
1.
  1. 从您提供的代码和描述中,我可以看到几个潜在的问题点,这些问题可能导致程序陷入死循环或者不能正确执行。下面是逐一分析和建议的修改:

  2. 数据读取错误:
  3. 您的代码中使用了 mov ax,[si] 来读取年份,但实际上您的年份数据是以字节(byte)形式存储的,而不是字(word)。因此,您应该使用 mov al,[si] 来读取一个字节到 AL 寄存器,并使用 mov ah,0 来确保 AH 为0(如果您的年份都是两位数的话)。然后,您可以考虑如何存储这个年份(比如,直接存储到 ES:[BX] 的位置,或者将其转换为字符形式存储)。
  4. 数据偏移量计算:
  5. 您在计算收入和雇佣人数的偏移量时使用了固定的偏移量(如 [di+168] 和 [si+84]),但这看起来并不正确。这些偏移量应该基于 BX 或 SI 的当前值动态计算,特别是如果您希望按照年份的顺序来访问这些数据。
  6. 循环控制:
  7. 您使用了 loop s 指令,但没有设置循环计数器(CX)。在 s 标签之前,您已经设置了 CX 为 21,这是正确的,但请确保在 loop 指令执行之前 CX 的值没有被意外修改。
  8. 除法操作:
  9. 您在使用 div 指令进行除法运算时,必须确保除数(这里是 es:[bx+10])不为零,否则会导致除零错误。您可能需要在执行除法之前检查除数是否为零。
  10. 字符存储:
  11. 如果您希望将年份、收入和雇佣人数转换为字符串形式存储在 table 段中,您需要编写额外的代码来处理这种转换。
  12. 下面是一个简化的示例,仅展示如何正确读取年份并存储到 table 段中(注意,这里未处理其他数据和转换):

  13. asm
  14. assume cs:code, ds:data, es:table  
  15.   
  16. data segment  
  17.     db '1975', '1976', ... ; 年份数据  
  18. data ends  
  19.   
  20. table segment  
  21.     db 21 dup('????') ; 预留空间存储年份字符串  
  22. table ends  
  23.   
  24. code segment  
  25. start:  
  26.     mov ax, data  
  27.     mov ds, ax  
  28.   
  29.     mov ax, table  
  30.     mov es, ax  
  31.   
  32.     mov bx, 0      ; ES:BX 指向 table 段  
  33.     mov cx, 21     ; 循环次数  
  34.     mov si, 0      ; DS:SI 指向年份数据  
  35.   
  36. s:  mov al, [si]   ; 读取年份的第一个字节  
  37.     mov es:[bx], al  
  38.     inc si  
  39.   
  40.     mov al, [si]   ; 读取年份的第二个字节  
  41.     mov es:[bx+1], al  
  42.     inc si  
  43.   
  44.     add bx, 2      ; 移动到 table 段的下一个位置  
  45.     loop s  
  46.   
  47.     mov ax, 4C00H  ; 退出到 DOS  
  48.     int 21H  
  49. code ends  
  50. end start
  51. 请注意,这个示例仅处理年份的读取和存储,未涉及其他数据的处理。您需要根据实际需求进一步扩展和修改代码。
复制代码

2.
  1. assume cs:code, ds:data, es:table
  2. data segment
  3. years db '1975','1976','1977',... ; 继续到1995
  4. incomes dd 16,22,...; 收入数据
  5. employees dw 3,7,...; 人员数据
  6. data ends

  7. table segment
  8. db 21 dup('year summ ne ?? ')
  9. table ends

  10. code segment
  11. start:
  12.     mov ax, data
  13.     mov ds, ax

  14.     mov ax, table
  15.     mov es, ax
  16.    
  17.     mov cx, 21          ; 设置循环次数为21
  18.     xor bx, bx          ; bx 用于存储偏移量,初始为0
  19.     xor si, si          ; si 用于年数据偏移
  20.     xor di, di          ; di 用于人员数据偏移

  21. s:
  22.     ; 读取年份
  23.     mov al, [years + si]  ; 读取年份
  24.     mov [es:bx], al       ; 存入 table
  25.     inc si                 ; 移动到下一个年份
  26.     add bx, 16             ; 更新表格位置

  27.     ; 读取人数
  28.     mov ax, [employees + di]
  29.     mov [es:bx], ax
  30.     add di, 2              ; 更新偏移
  31.     add bx, 2              ; 更新表格位置

  32.     ; 读取收入
  33.     mov eax, [incomes + si]
  34.     ; 修改计算逻辑,根据需要进行计算

  35.     ; 检查循环是否完成
  36.     loop s                 ; 如果 cx 不为0,则继续循环

  37.     ; 程序结束
  38.     mov ax, 2C00H
  39.     int 21H

  40. code ends
  41. end start
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-8-8 01:15:19 | 显示全部楼层
本帖最后由 jackz007 于 2024-8-8 01:21 编辑
  1. assume cs:code,ds:data,es:table

  2. stack segment para stack 'STACK'
  3.     db 400h dup(0)
  4. stack ends

  5. data segment para public 'DATA'
  6. db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
  7. db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
  8. db '1993','1994','1995'
  9. dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
  10. dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
  11. dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
  12. dw 11542,14430,15257,17800
  13. data ends

  14. table segment para public 'TABLE'
  15. db 21 dup('year summ ne ?? ')
  16. table ends

  17. code segment para public 'CODE'
  18. ; 初始化数据段地址
  19. start: mov ax,data
  20.        mov ds,ax
  21.        mov ax,table
  22.        mov es,ax
  23. ; 以年为单位,向 table 表传输 21 个年份
  24.        xor si,si
  25.        push si
  26.        pop di
  27.        cld
  28.        mov cx,21
  29. s1:    movsw
  30.        movsw
  31.        add di,12
  32.        loop s1
  33. ; 向 table 表传输 21 年中,每一年的总收入
  34.        mov di,5
  35.        mov cx,21
  36. s2:    movsw
  37.        movsw
  38.        add di,12
  39.        loop s2
  40. ; 向 table 表传输 21 年中,每一年的雇员人数,并计算出人均收入,存入 table 表中
  41.        xor bx,bx
  42.        mov di,10
  43.        mov cx,21
  44. s3:    movsw
  45.        mov ax,word ptr es:[bx+5]
  46.        mov dx,word ptr es:[bx+7]
  47.        div word ptr es:[bx+10]
  48.        mov word ptr es:[bx+13],ax      
  49.        add di,14
  50.        add bx,16
  51.        loop s3

  52.        mov ax,4c00h
  53.        int 21h
  54. code ends
  55. end start
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-5-10 01:05

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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