一只程序猫 发表于 2023-8-1 11:35:35

实验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

isdkz 发表于 2023-8-1 11:35:48

这段代码是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时正常显示结果了。

希望以上解释对您有所帮助。如果您有更多问题,请随时问我。

陶远航 发表于 2023-8-1 11:35:58

你的汇编代码存在一些问题,可能导致在直接运行 .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 指令的位置。

请尝试使用修正后的代码重新汇编并运行,看看是否能够正常显示结果。如果还有其他问题,请随时问我。
如果问题已经解决,请设置最佳答案

一只程序猫 发表于 2023-8-1 11:43:37

isdkz 发表于 2023-8-1 11:35
这段代码是8086汇编语言的程序,用于将一个整数(12666)转换成字符串并在屏幕上显示。根据您的问题描述, ...

并不是,我设置了

一只程序猫 发表于 2023-8-1 11:46:13

陶远航 发表于 2023-8-1 11:35
你的汇编代码存在一些问题,可能导致在直接运行 .exe 文件时出错。以下是修正后的代码:




reversal:
    pop ax
    add ax, 30h
    mov es:, al
    inc si
    loop reversal
    ret
mov es:, al肯定有问题

一只程序猫 发表于 2023-8-1 11:54:03

各位大神们

一只程序猫 发表于 2023-8-1 14:25:52

知道为什么了,取余那里有问题,虽然还是不清楚为什么在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]
查看完整版本: 实验10第三题疑惑,求各位大神解惑