实验10(3)的扩展
本帖最后由 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:,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:,dl
ret
unknowloop: div bx
add dl,30h
mov ds:,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:,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:
mov es:,dl;存数字ASCII码
mov es:.1,al;存字符属性
inc si
add di,2
loop save_str
retpoint: ret
code ends
end start 汇编程序调试分析与建议
您遇到的问题主要出现在取十位数字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 来存储 dl。
3. 修改建议:
- 在 unknowloop 中的存储行,确保偏移使用正确:
unknowloop: div bx
add dl,30h
mov ds:,dl
mov cx,ax
jcxz retpoint
dec si
jmp short unknowloop
4. 可能还有 其他需要注意的地方:
- 确保 si 的初始值和递减操作都正确无误。
- 请确认段地址和偏移量设置正确,以避免没有正确访问内存的问题。
根据上述建议,您可以在调试器中逐步执行代码,检查寄存器状态和内存内容变化,以进一步确定问题所在。如果有条件,可以使用单步执行和断点精确定位到引发错误的代码行,并进行调试和修正。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 我就是单步调试,没明白???【bx+si】这个错误提示什么意思。因为mov ds:,dl这句代码和前天发布的实验10(3)没什么区别啊。 laocaiye 发表于 2025-03-06 10:28
我就是单步调试,没明白???【bx+si】这个错误 ...
对于汇编语言,`mov ds:, dl` 中的 `ds:` 应该解释为 `ds` 段中的某个偏移地址。这里没有指定偏移,可能会出现错误。应该使用 `` 这样的偏移来指定内存位置:
unknowloop: div bx
add dl,30h
mov , dl ; 将数字存到数据段的正确偏移位置
mov cx, ax
jcxz retpoint
dec si
jmp short unknowloop
具体原因:
1. **错误提示**:`【bx+si】` 这样的错误提示可能表示内存操作数未正确定义。汇编语言中,通常需要用括号表示内存引用,例如 ``。
2. **偏移地址**:在 `mov , dl` 中,`` 表示使用基址寄存器 `bx` 和变址寄存器 `si` 共同指向内存地址。这是符合汇编语法的标准格式。
请尝试用上述修改版本调试程序,看看问题是否得到解决。同时继续使用调试器(如 `DEBUG` 或 `gdb`),逐步检查寄存器和内存状态。这将有助于更准确地找到问题所在。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 我把除数给了di,不在使用bx,也使用了你的建议,同时前面教材已给定代码顺序也调整了下:
mov ax,data
mov ds,ax
mov dx,0
mov ax,12345
但是执行时同样的问题提示。请小鱼老师调试完整代码,帮助找出问题所在。 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 , dl ; 在这你应该指定偏移
ret
unknowloop:
div di
add dl, 30h
mov , dl ; 使用正确的偏移进行存储
mov cx, ax
jcxz retpoint
dec si
jmp short unknowloop
loopfive:
mov cx, 5
five:
div di
add dl, 30h
mov , 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,
mov , dl
mov , al
inc si
add di, 2
loop save_str
retpoint:
ret
code ends
end start
### 改动要点:
- 使用 `mov , dl` 而不是 `mov ds:, dl`。确保在进行内存访问时,明确指定偏移。
- 确保所有指令后的 `[]` 指定的是偏移。
- 确保 `ds` 和其他段寄存器的使用及其保存的数据是正确均衡的。
请使用上述代码进行调试。如问题依然存在,建议查看段寄存器设定及内存访问的详细规范,以确保符合汇编语言环境的标准要求。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 laocaiye 发表于 2025-03-06 11:12
g:\asm_code\error.png
请将错误信息描述文字或详细地描述问题,以便更好地帮助您解决问题。可以包括错误提示的文本信息、代码的执行位置(如果有)以及其他可能有助于理解问题的信息。这样我可以更精准地提供帮助和建议。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 完全复制你的代码,执行时还是同样错误。小鱼老师不能亲自出马看下吗? 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 , dl ; 在这你应该指定偏移
ret
unknowloop:
div di
add dl, 30h
mov , dl ; 使用正确的偏移进行存储
mov cx, ax
jcxz retpoint
dec si
jmp short unknowloop
loopfive:
mov cx, 5
five:
div di
add dl, 30h
mov , 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,
mov es:, dl
mov es:, al
inc si
add di, 2
loop save_str
retpoint:
ret
code ends
end start
关键调整:
- 在内存访问如 `mov , dl` 时,明确使用中括号表示 ds 段的偏移地址。
- 确保寄存器在内存访问前已经正确指向目标地址。
请再次尝试上述代码,如果还有问题,请提供详细的错误信息以帮助我们继续诊断。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页:
[1]