鱼C论坛

 找回密码
 立即注册
查看: 144|回复: 8

实验10(3)的扩展

[复制链接]
发表于 2025-3-6 10:17:52 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 laocaiye 于 2025-3-6 17:03 编辑

前天发布了实验10(3)的基础版思路。昨天开始梳理扩展思路,分三种情况,为便于理解我的程序,现结合我的代码含义进行说明和解释,便于大家找出我代码的问题
1、当dx=0时,跳转到 dx_is0 标号处,然后又分两种情况
  (1)当ax=0时,说明要操作的数据=0,此时跳到num_is0 标号处。这个情况已测试,代码没问题
  (2)当ax=0时,考虑数据位数未知情况,跳转到unknowloop,意思是未知循环次数。当前代码就是测试这个情况,
        在测试时,个位数字5已正确取数存入数据段偏移地址9处。但是当取十位数字4时,运行到mov ds:[si],dl时出现问题。
        因为也是刚学汇编,知识有限,没找出问题所在。请各路大神编译,debug下。
2、当dx !=0 时,又分两步执行:
    第一步:先对ax中的数连续取5次数字,即执行loopfive 标号代码
    第二步:把dx高16位数据给ax,考虑到高16位数据位数未知情况,仍需执行 unknowloop 标号处代码

请各位大神先对红色字体问题做测试,帮忙找出问题所在。有兴趣的再继续研究第三种情况执行时会出现的错误。
拜托费心!


assume cs:code

data segment
        db 10 dup(0)
data ends

code segment

start:                mov dx,0
                        mov ax,12345
                        mov bx,data
                        mov ds,bx
                        mov si,0
                       
                        call dtoc
                       
                        mov dh,8;8行
                        mov dl,3;3列
                        mov cl,2;字符属性
                       
                        call show_str

                        mov ax,4c00h
                        int 21h
               
dtoc:                mov si,9;现在不知道数字个数,所以从数据段最大偏移地址开始保存数据
                        mov bx,10;设置除数10给bx,每次去除被除数,取余数即为要的数字
                       
                        mov cx,dx
                        jcxz dx_is0;如果dx=0,只需考虑ax,然后ax分两种情况:ax = 0和ax != 0
                        push dx;当高16为dx != 0时,因为下面要复用dx寄存器,所以先把dx入栈
                        call loopfive;因为高位dx不为0,所以低位肯定是5位数字,直接循环5次取数
                        pop dx;低位5个数字字符转化完成后,把入栈的dx弹栈,然后交给ax
                        mov ax,dx
                        jmp unknowloop
                       
dx_is0:                mov cx,ax
                        jcxz num_is0;即当这个数为0时,跳到num_is0执行,然后返回
                        jmp unknowloop;如果dx=0,但是ax != 0时,因为ax位数未知,所以转到未知循环模块,从此模块返回点返回
                       
num_is0:        mov dl,0
                        add dl,30h
                        mov ds:[si],dl
                        ret
                       
unknowloop:        div bx
                        add dl,30h
                        mov ds:[si],dl
                        mov cx,ax
                        jcxz retpoint
                        dec si
                        jmp short unknowloop
                       
                       
loopfive:        mov cx,5
                                               
        five:        div bx;除法结果:ax存商,也即是下一步的被除数,dx保存余数,即要取的数字
                        add dl,30h;因为余数是一位数字,保存在dx寄存器的低8位dl中。再加30h转化为对应的ASCII码
                        mov ds:[si],dl;
                        dec si
                        loop five
                        ret
                       
                       
                       
show_str:        mov ax,0b800h;把显示段给附加段
                        mov es,ax
                       
                        mov al,160;计算显示段偏移地址
                        mul dh
                        mov di,ax;此时di中存储的是第8行的首地址
                        mov al,2;每列占2个字节。计算3列的偏移地址,为方便下面传值,直接把3列的偏移地址加到di上
                        mul dl;dl中存储的是列数3
                        add di,ax;di定位到显示段的第8行第3列
                       
                        mov al,cl;此时al中存储是字符属性值2
                       
                        mov cx,10;通过cx-si的值判断数字是否已传递完成。
save_str:        sub cx,si
                        jcxz retpoint
                        mov dl,ds:[si]
                        mov es:[di],dl;存数字ASCII码
                        mov es:[di].1,al;存字符属性
                        inc si
                        add di,2
                        loop save_str
                       
retpoint:        ret
code ends

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

使用道具 举报

发表于 2025-3-6 10:18:39 | 显示全部楼层
汇编程序调试分析与建议

您遇到的问题主要出现在取十位数字4时的保存操作上。我们来看代码中的相关部分:

1. 在 dtoc 过程:
unknowloop:        div bx
                        add dl,30h
                        mov ds:,dl
                        mov cx,ax
                        jcxz retpoint
                        dec si
                        jmp short unknowloop

2. 问题可能出现的原因:

- 在 mov ds:,dl 这行代码中,您可能忘记为段地址的偏移指定具体位置。应在 ds:[si] 中使用偏移 si 来存储 dl

3. 修改建议:

- 在 unknowloop 中的存储行,确保偏移使用正确:
unknowloop:        div bx
                        add dl,30h
                        mov ds:[si],dl
                        mov cx,ax
                        jcxz retpoint
                        dec si
                        jmp short unknowloop

4. 可能还有 其他需要注意的地方

- 确保 si 的初始值和递减操作都正确无误。
- 请确认段地址和偏移量设置正确,以避免没有正确访问内存的问题。

根据上述建议,您可以在调试器中逐步执行代码,检查寄存器状态和内存内容变化,以进一步确定问题所在。如果有条件,可以使用单步执行和断点精确定位到引发错误的代码行,并进行调试和修正。

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

使用道具 举报

 楼主| 发表于 2025-3-6 10:28:18 | 显示全部楼层
我就是单步调试,没明白  ???  【bx+si】这个错误提示什么意思。因为mov ds:[si],dl这句代码和前天发布的实验10(3)没什么区别啊。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-3-6 10:28:35 | 显示全部楼层
laocaiye 发表于 2025-03-06 10:28
我就是单步调试,没明白  ???  【bx+si】这个错误 ...


对于汇编语言,`mov ds:, dl` 中的 `ds:` 应该解释为 `ds` 段中的某个偏移地址。这里没有指定偏移,可能会出现错误。应该使用 `[bx+si]` 这样的偏移来指定内存位置:
unknowloop:        div bx
                        add dl,30h
                        mov [bx+si], dl                ; 将数字存到数据段的正确偏移位置
                        mov cx, ax
                        jcxz retpoint
                        dec si
                        jmp short unknowloop

具体原因:

1. **错误提示**:`【bx+si】` 这样的错误提示可能表示内存操作数未正确定义。汇编语言中,通常需要用括号表示内存引用,例如 `[bx+si]`。
   
2. **偏移地址**:在 `mov [bx+si], dl` 中,`[bx+si]` 表示使用基址寄存器 `bx` 和变址寄存器 `si` 共同指向内存地址。这是符合汇编语法的标准格式。

请尝试用上述修改版本调试程序,看看问题是否得到解决。同时继续使用调试器(如 `DEBUG` 或 `gdb`),逐步检查寄存器和内存状态。这将有助于更准确地找到问题所在。

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

使用道具 举报

 楼主| 发表于 2025-3-6 10:43:35 | 显示全部楼层
我把除数给了di,不在使用bx,也使用了你的建议,同时前面教材已给定代码顺序也调整了下:
mov ax,data
mov ds,ax
mov dx,0
mov ax,12345

但是执行时同样的问题提示。请小鱼老师调试完整代码,帮助找出问题所在。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-3-6 10:43:58 | 显示全部楼层
laocaiye 发表于 2025-03-06 10:43
我把除数给了di,不在使用bx,也使用了你的建议,同时 ...


您使用的汇编语言可能对内存操作有严格的要求。出现 “【bx+si】” 的错误提示可能是因为没有正确设置内存操作数,尤其是在合适的寄存器上。我们来仔细看一下您的代码,并做出一些调整建议:

请留意以下几点改动:

1. 确保使用的数据段和偏移量是绝对符合汇编语言规范的。
2. 调整代码以精确指定内存引用偏移,尤其是在使用 `ds` 段时。

以下是调整了的代码片段:
assume cs:code

data segment
    db 10 dup(0)
data ends

code segment

start:
    mov ax, data
    mov ds, ax
    mov dx, 0
    mov ax, 12345
    mov di, 10
    mov si, 0

    call dtoc

    mov dh, 8 ;8行
    mov dl, 3 ;3列
    mov cl, 2 ;字符属性

    call show_str

    mov ax, 4c00h
    int 21h

dtoc:
    mov si, 9 ; 从数据段最大偏移地址开始保存数据
    mov di, 10 ; 这里使用di用于除数操作,每次除10

    mov cx, dx
    jcxz dx_is0 ;如果dx=0,只需考虑ax
    push dx
    call loopfive
    pop dx
    mov ax, dx
    jmp unknowloop

dx_is0:
    mov cx, ax
    jcxz num_is0 ; 当数字为0时
    jmp unknowloop

num_is0:
    mov dl, 0
    add dl, 30h
    mov [si], dl ; 在这你应该指定偏移
    ret

unknowloop:
    div di
    add dl, 30h
    mov [si], dl ; 使用正确的偏移进行存储
    mov cx, ax
    jcxz retpoint
    dec si
    jmp short unknowloop

loopfive:
    mov cx, 5
five:
    div di
    add dl, 30h
    mov [si], dl
    dec si
    loop five
    ret

show_str:
    mov ax, 0b800h
    mov es, ax

    mov al, 160
    mul dh
    mov di, ax
    mov al, 2
    mul dl
    add di, ax

    mov al, cl
    mov cx, 10
save_str:
    sub cx, si
    jcxz retpoint
    mov dl, [si]
    mov [es:di], dl
    mov [es:di+1], al
    inc si
    add di, 2
    loop save_str

retpoint:
    ret
code ends

end start

### 改动要点:

- 使用 `mov [si], dl` 而不是 `mov ds:, dl`。确保在进行内存访问时,明确指定偏移。
- 确保所有指令后的 `[]` 指定的是偏移。
- 确保 `ds` 和其他段寄存器的使用及其保存的数据是正确均衡的。

请使用上述代码进行调试。如问题依然存在,建议查看段寄存器设定及内存访问的详细规范,以确保符合汇编语言环境的标准要求。

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

使用道具 举报

发表于 2025-3-6 11:12:51 | 显示全部楼层


请将错误信息描述文字或详细地描述问题,以便更好地帮助您解决问题。可以包括错误提示的文本信息、代码的执行位置(如果有)以及其他可能有助于理解问题的信息。这样我可以更精准地提供帮助和建议。

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

使用道具 举报

 楼主| 发表于 2025-3-6 11:17:27 | 显示全部楼层
完全复制你的代码,执行时还是同样错误。小鱼老师不能亲自出马看下吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-3-6 11:18:03 | 显示全部楼层
laocaiye 发表于 2025-03-06 11:17
完全复制你的代码,执行时还是同样错误。小鱼老师不能 ...


非常抱歉给您带来了困扰。根据您描述的问题,可能因为在内存存取时没有正确指定偏移地址,导致段错误。下面是重新调整的版本,其中确保在每一次内存访问时明确指定偏移:
assume cs:code

data segment
    db 10 dup(0)
data ends

code segment

start:
    mov ax, data
    mov ds, ax
    mov dx, 0
    mov ax, 12345
    mov di, 10
    mov si, 0

    call dtoc

    mov dh, 8 ;8行
    mov dl, 3 ;3列
    mov cl, 2 ;字符属性

    call show_str

    mov ax, 4c00h
    int 21h

dtoc:
    mov si, 9 ; 从数据段最大偏移地址开始保存数据
    mov di, 10 ; 这里使用di用于除数操作,每次除10

    mov cx, dx
    jcxz dx_is0 ;如果dx=0,只需考虑ax
    push dx
    call loopfive
    pop dx
    mov ax, dx
    jmp unknowloop

dx_is0:
    mov cx, ax
    jcxz num_is0 ; 当数字为0时
    jmp unknowloop

num_is0:
    mov dl, 0
    add dl, 30h
    mov [si], dl ; 在这你应该指定偏移
    ret

unknowloop:
    div di
    add dl, 30h
    mov [si], dl ; 使用正确的偏移进行存储
    mov cx, ax
    jcxz retpoint
    dec si
    jmp short unknowloop

loopfive:
    mov cx, 5
five:
    div di
    add dl, 30h
    mov [si], dl
    dec si
    loop five
    ret

show_str:
    mov ax, 0b800h
    mov es, ax

    mov al, 160
    mul dh
    mov di, ax
    mov al, 2
    mul dl
    add di, ax

    mov al, cl
    mov cx, 10
save_str:
    sub cx, si
    jcxz retpoint
    mov dl, [si]
    mov es:[di], dl
    mov es:[di+1], al
    inc si
    add di, 2
    loop save_str

retpoint:
    ret
code ends

end start

关键调整:
- 在内存访问如 `mov [si], dl` 时,明确使用中括号表示 ds 段的偏移地址。
- 确保寄存器在内存访问前已经正确指向目标地址。

请再次尝试上述代码,如果还有问题,请提供详细的错误信息以帮助我们继续诊断。

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-3-31 09:10

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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