实验10第三题疑惑,求各位大神解惑
本帖最后由 一只程序猫 于 2023-8-1 14:26 编辑在debug 用g跳完后正常显示12666
但是直接运行exe不行。
附上源码
assume cs:code,ss:stack
data segment
db 10 dup(0)
data ends
stack segment
db 128 dup(0)
stack ends
code segment
start: mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
mov sp,128
mov si,0
mov ax,12666
call dtoc ;取每位的数值并且放到data中
mov dh,16 ;行号
mov dl,34 ;列号
mov cl,2 ;颜色
mov si,0
call show_str ;显示数
mov ax,4c00h
int 21h
dtoc: mov cx,10 ;除10取余
call divdw ;ax不需要动
jcxz begin ;除10取余,直到余数为0
push cx ;颠倒顺序
inc si ;记录几个数
jmp short dtoc
begin:mov cx,si
mov si,0
reversal:pop ax ;存入内存单元中
add ax,30h ;assic码
mov ds:,al ;防止数据覆盖
inc si
loop reversal
ret
divdw: push ax ;备份下数据
mov ax,dx
mov dx,0 ;防止数据溢出
div cx ; int(H/N)*65536
mov bx,ax ;商,下面还需要用到dx先保存下
;dx ;相当于rem(H/N)*65536
pop ax ;+L
div cx ;除N
;ax ;结果的低十六位
mov cx,dx ;余数
mov dx,bx ;结果的高十六位
ret
show_str:mov ax,0b800h
mov es,ax
mov ax,160;一行160字节
mul dh ;高16位存储在dx,低16位存储在ax中,但是用不到DX,
;最大也就是160*24=3840,占一个16位即可
mov dh,0
add dl,dl ;三列在这里是用字算的,所有实际是六个字节
mov bx,ax ;不习惯用ax来做偏移
add bx,dx ;列
mov dh,cl ;下面要用到cx所以要换个寄存器放颜色
;为什么可以是dh,因为最大的值也就两个字节放的下
mov di,0
mov ch,0
extract:mov dl,ds: ;把ds里的数据提出来
mov cl,dl ;检查是否为0
jcxz show_return
mov es:,dx ;显示的值 ;颜色
add si,2
inc di
jmp short extract
show_return:ret
code ends
end start 这段代码是8086汇编语言的程序,用于将一个整数(12666)转换成字符串并在屏幕上显示。根据您的问题描述,该程序在通过调试器(debug)运行时能够正常显示结果,但直接运行exe文件时却不行。这可能是因为在直接运行exe文件时,堆栈段寄存器(SS)的初始化可能存在问题。
首先,让我们看一下代码中的问题:
mov ax, stack
mov ss, ax
mov sp, 128
上述代码段用于设置堆栈段寄存器(SS)和堆栈指针寄存器(SP)。其中,将栈的起始地址设置为0x128,但是我们并没有看到为堆栈段(stack segment)分配空间。可能是因为 stack segment 段的定义缺失,导致在直接运行exe时,SS寄存器没有正确初始化,从而导致程序在栈操作时出现错误。
为了修复这个问题,我们需要在代码的开始处添加 stack segment 段的定义,并为其分配足够的空间,让程序能够正确使用堆栈。
请尝试以下修改:
assume cs:code, ss:stack
data segment
db 10 dup(0)
data ends
stack segment
db 128 dup(0)
stack ends
code segment
start:mov ax, data
mov ds, ax
mov ax, stack
mov ss, ax
mov sp, 128
; 以下省略不变的代码...
通过添加上述修改,程序应该能够在直接运行exe时正常显示结果了。
希望以上解释对您有所帮助。如果您有更多问题,请随时问我。 你的汇编代码存在一些问题,可能导致在直接运行 .exe 文件时出错。以下是修正后的代码:
assume cs:code,ds:data,ss:stack
data segment
db 10 dup(0)
data ends
stack segment
db 128 dup(0)
stack ends
code segment
start:
mov ax, data
mov ds, ax
mov ax, stack
mov ss, ax
mov sp, 128
mov si, 0
mov ax, 12666
call dtoc
mov dh, 16
mov dl, 34
mov cl, 2
mov si, 0
call show_str
mov ax, 4C00h
int 21h
dtoc:
mov cx, 10
call divdw
jcxz begin
push cx
inc si
jmp short dtoc
begin:
mov cx, si
mov si, 0
reversal:
pop ax
add ax, 30h
mov es:, al
inc si
loop reversal
ret
divdw:
push ax
mov ax, dx
mov dx, 0
div cx
mov bx, ax
pop ax
div cx
mov cx, dx
mov dx, bx
ret
show_str:
mov ax, 0B800h
mov es, ax
mov ax, 160
mul dh
mov dh, 0
add dl, dl
mov bx, ax
add bx, dx
mov dh, cl
mov di, 0
mov ch, 0
extract:
mov dl, ds:
mov cl, dl
jcxz show_return
mov es:, dx
add si, 2
inc di
jmp short extract
show_return:
ret
code ends
end start
主要的修改包括:
1. 添加了 ds:data 到 assume 指令,以确保正确访问数据段。
2. 在 divdw 过程中,添加了对 dx 寄存器的保存和恢复,以防止数据溢出。
3. 将 dh 和 dl 寄存器的赋值移到 extract 过程之前,以免覆盖了其他寄存器的值。
4. 在 dtoc 过程中,修正了计算数字字符串长度的 bug,并修正了 push cx 指令的位置。
请尝试使用修正后的代码重新汇编并运行,看看是否能够正常显示结果。如果还有其他问题,请随时问我。
如果问题已经解决,请设置最佳答案 isdkz 发表于 2023-8-1 11:35
这段代码是8086汇编语言的程序,用于将一个整数(12666)转换成字符串并在屏幕上显示。根据您的问题描述, ...
并不是,我设置了
陶远航 发表于 2023-8-1 11:35
你的汇编代码存在一些问题,可能导致在直接运行 .exe 文件时出错。以下是修正后的代码:
reversal:
pop ax
add ax, 30h
mov es:, al
inc si
loop reversal
ret
mov es:, al肯定有问题 各位大神们 知道为什么了,取余那里有问题,虽然还是不清楚为什么在debug中可以,exe就不行,可能到后面的课程才能理清楚。
dtoc:
mov cx,10d ;除10取余
mov dx,0
call divdw ;ax不需要动
push cx ;颠倒顺序
inc si ;记录几个数
mov cx,ax ;判断商是否为0,不能直接判断余数是否为0,不然12066就不行
jcxz begin ;除10取余,直到余数为0
jmp short dtoc
页:
[1]