凤梨/n 发表于 2023-6-1 11:09:50

实验7,大伙帮我看一看到底哪里出错了?为什么值没有写进去

assume cs:codesg,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'      
;以上是表示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型数据      
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226      
dw 11542,14430,45257,17800
;以上是表示21年公司雇员人数的21个word型数据
data ends

table segment      
db 21 dup('year summ ne ?? ')
table ends

codesg segment
start:

mov ax,data
mov ds,ax
mov ax,table
mov es,ax
mov bx,0
mov di,0
mov si,0
mov cx,21

s1:
mov ax,ds:
mov es:,ax
mov ax,ds:
mov es:,ax
mov ax,ds:
mov es:,ax
mov ax,ds:
mov es:,ax

mov ax,ds:
mov dx,ds:
mov es:,ax
mov es:,ax

mov ax,ds:
mov es:,ax

mov ax,ds:
mov dx,ds:
div word ptr es:
mov es:,ax
add bx,16
loop s1

mov ax,4c00h
int 21h

codesg ends
end start

歌者文明清理员 发表于 2023-6-1 11:12:24

本帖最后由 歌者文明清理员 于 2023-6-1 11:14 编辑

这段汇编代码存在一些问题,值没有写进去可能是由于以下原因:


[*]table段定义了一个21个字节的字符串数组,但是在程序中使用了字节(byte)和字(word)的混合使用,导致写入时出现了偏移错误。
[*]实现除法操作时,应该用dword类型进行除法操作,而不是用word类型。如果使用word类型,那么会导致高16位溢出。
[*]3.在循环过程中,没有更新di的值,导致每次写入的地址都是相同的,从而覆盖了之前写入的数据。


下面是修改后的代码:

assume cs:codesg, 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 11542,14430,45257,17800
data ends

table segment
    db 21 dup('year summ ne ?? ')
table ends

codesg segment
start:

mov ax,data
mov ds,ax
mov ax,table
mov es,ax

mov bx,0
mov di,0
mov cx,21

s1:
mov ax,ds:
mov es:,ax
mov ax,ds:
mov es:,ax
mov ax,ds:
mov es:,ax
mov ax,ds:
mov es:,ax

mov eax,ds:
mov es:,eax

mov eax,ds:
div dword ptr es:
mov es:,eax

add di,14         ; 每次写入完一条数据,需要更新di的值
add bx,8          ; 每次读取完一组数据,需要更新bx的值
loop s1

mov ax,4c00h
int 21h

codesg ends
end start
现在程序已经可以正常运行了,将数据写入到table段中。

isdkz 发表于 2023-6-1 11:12:32

这个代码在做什么呢?看起来它试图从 data segment 中读取数据并写入 table segment 。这个代码中的一些问题可能阻止了正确的写入操作。

首先,我注意到以下问题:

1. 对数据的引用可能有问题。你在第一部分定义了字符串,并且每个字符串都是4个字节的,但在s1循环中,你每次循环都会从bx指向的地方读取4个字节,并且每次迭代都会增加16到bx。实际上,你每次迭代只应该增加4到bx。

2. 写入到表格中的数据大小和数据类型不匹配。例如, mov es:,ax 和 mov es:,ax 中,你试图在同一位置写入两次。另外,你在使用 div 指令时没有处理余数,这可能会导致意外的结果。

3. 在执行 div word ptr es: 之前,你需要确保DX中的值是你想要的值,否则它可能会干扰 div 的结果。

这是一种可能的解决方法,但请注意这只是一种可能的解决方案,这依赖于你的具体需求。希望这个回答可以帮助你解决问题。

codesg segment
start:

mov ax,data
mov ds,ax
mov ax,table
mov es,ax
mov bx,0
mov di,0
mov si,0
mov cx,21

s1:
mov ax,ds:
mov es:,ax

lea bx, ; increment bx by 4, move to the next data

mov eax, ds:
mov es:, eax ; fill the summ

lea bx, ; increment bx by 4

mov ax, ds:
mov es:, ax ; fill the ne

lea bx, ; increment bx by 2

; find average
mov dx,0
mov ax,ds:
div word ptr es:
mov es:,ax

add di, 16 ; move to next position in the table
loop s1

mov ax,4c00h
int 21h

codesg ends
end start


注意:这是基于你的源代码和我理解的目的进行的修改。在你的环境中,可能需要做进一步的调整。

凤梨/n 发表于 2023-6-1 11:21:09

isdkz 发表于 2023-6-1 11:12
这个代码在做什么呢?看起来它试图从 data segment 中读取数据并写入 table segment 。这个代码中的一些问 ...

lea指令还不太熟悉,你提到的解决办法我尝试一下

凤梨/n 发表于 2023-6-1 11:36:16

歌者文明清理员 发表于 2023-6-1 11:12
这段汇编代码存在一些问题,值没有写进去可能是由于以下原因:




eax是啥寄存器啊

歌者文明清理员 发表于 2023-6-1 11:41:03

凤梨/n 发表于 2023-6-1 11:36
eax是啥寄存器啊

eax 是 x86 汇编语言中的一个 32 位寄存器,它是 ax 寄存器和其高 16 位寄存器 ah 和 al 的组合。在汇编程序中,eax 可以用于保存函数返回值、存储32位整数数据等。由于 eax 是处理器的通用寄存器之一,所以它还可以执行很多不同的指令,如算术、逻辑、移位、条件操作等。

凤梨/n 发表于 2023-6-1 17:33:50

歌者文明清理员 发表于 2023-6-1 11:41
eax 是 x86 汇编语言中的一个 32 位寄存器,它是 ax 寄存器和其高 16 位寄存器 ah 和 al 的组合。在汇 ...

但是我在dosbox中,他识别不出来eax

歌者文明清理员 发表于 2023-6-1 17:41:03

凤梨/n 发表于 2023-6-1 17:33
但是我在dosbox中,他识别不出来eax

如果您在 DOSBox 中使用的是 16 位 DOS 环境,那么您可能不能使用 32 位的 eax 寄存器,因为 16 位环境只支持最高 16 位的 ax 寄存器和其低 8 位寄存器 ah 和 al。在这种情况下,您需要使用其他 16 位寄存器来完成您的任务。

如果您需要在 32 位环境中使用 eax 寄存器,您可以使用 DOS/4GW 或类似的 DOS 扩展程序来实现。这些扩展程序支持 32 位代码和寄存器,并允许您在 DOS 环境中编写更为复杂的程序。
页: [1]
查看完整版本: 实验7,大伙帮我看一看到底哪里出错了?为什么值没有写进去