【问题标题】:Assembly Procedures not running Intel 8086装配程序不运行 Intel 8086
【发布时间】:2015-07-18 01:49:04
【问题描述】:

下面的代码应该获得 20 个用户输入的数字(6 位数字或更少)并计算平均值并对它们进行排序,当我将其设置为获得 6 个或更少的数字时,它工作正常。但是当它设置为获取 7-20 个数字时,在获取数字后,它会跳过下一个过程,有时会再次运行 GetNum 过程(从用户那里获取数字的那个),当它得到 11 个数字时,我会收到此消息“程序已将控制权交还给操作系统”。

ShowMsg macro msg
mov ah, 09h
mov dx, offset msg
int 21h
endm

NewLine macro
mov ah, 02h
mov dl, 0ah
int 21h
mov dl, 0dh
int 21h
endm


data segment
sum   dd 0
num   dd 0
ave   dd 0
array dd 20 dup(0)
msg1  db 'Enter 20 numbers:', '$'
msg2  db 0dh,0ah,'Average: ', '$'
temp  dd ?
data ends 

stack segment
dd 100 dup(?)
stack ends

code segment
assume cs:code, ds:data, ss:stack
Main Proc Far

    mov ax, data
    mov ds, ax
    mov ax, stack
    mov ss, ax

    ;Printing first message.
    ShowMsg msg1

    call GetNum

    call Average

    call Sort

    call Print

    mov ah, 4ch
    int 21h

Main endp

proc GetNum  

    mov bp, 0
    mov ch, 20

    NextNumber:
    NewLine

    mov cl, 6
    mov word ptr num, 0
    mov word ptr num+2, 0

    GetChar:    
    mov ah, 07h
    int 21h

    cmp al, 0dh
    jz Flag

    cmp al, 30h
    jb GetChar

    cmp al, 39h
    ja GetChar

    mov ah, 02h
    mov dl, al
    int 21h

    sub al, 30h

    mov bl, al
    mov di, 10
    mov ax, num
    mul di

    mov num, ax
    push dx

    mov ax, num+2
    mul di

    mov num+2, ax
    pop dx
    add num+2, dx

    mov bh, 0
    add num, bx
    adc word ptr num+2, 0

    dec cl
    jnz GetChar

    Flag:
    mov ax, num
    mov dx, num+2

    mov array[bp], ax
    mov array[bp+2], dx
    add bp, 4 

    add sum, ax
    adc sum+2, dx

    dec ch
    jnz NextNumber

    ret

GetNum endp

proc Average 

    mov bx, 20
    mov dx, 0
    mov ax, word ptr sum+2
    div bx 

    mov word ptr ave+2, ax
    mov ax, word ptr sum
    div bx
    mov word ptr ave, ax

    ShowMsg msg2

    mov cl, 0
    Next1:
    mov bx, 10
    mov dx, 0
    mov ax, word ptr ave+2
    div bx

    mov word ptr ave+2, ax 
    mov ax, word ptr ave
    div bx
    mov word ptr ave, ax

    push dx
    inc cl

    cmp ave, 0
    jnz Next1

    Next2:
    pop dx
    add dl, 30h
    mov ah, 02h
    int 21h

    dec cl
    jnz Next2

    NewLine

    ret

Average endp 

proc Sort 

    mov ch, 20

    OuterFor:
    mov bp, 0

    Cmp1:
    mov ax, array[bp+2] 
    mov bx, array[bp+6]

    cmp ax,bx
    ja Xchange 

    cmp ax,bx
    jz Cmp2

    jmp Next

    Cmp2:
    mov ax, array[bp]
    mov bx, array[bp+4]
    cmp ax, bx
    ja Xchange

    jmp Next

    Xchange:
    mov ax, array[bp]
    mov dx, array[bp+2]
    mov temp, ax
    mov temp+2, dx
    mov ax, array[bp+4]
    mov dx, array[bp+6]
    mov array[bp], ax
    mov array[bp+2], dx
    mov ax, temp
    mov dx, temp+2
    mov array[bp+4], ax
    mov array[bp+6], dx
    Next:
    add bp, 4
    cmp bp, 76
    jnz Cmp1 

    dec ch
    jnz OuterFor

    ret

Sort endp

proc Print 

    mov bp, 0
    C: 
    mov cl, 0
    A:
    mov bx, 10
    mov dx, 0
    mov ax, array[bp+2]
    div bx

    mov array[bp+2], ax 
    mov ax, array[bp]
    div bx
    mov array[bp], ax

    push dx
    inc cl
    mov ax, array[bp]
    mov dx, array[bp+2]
    or ax, dx
    jnz A

    B:
    pop dx
    add dl, 30h
    mov ah, 02h
    int 21h

    dec cl
    jnz B 

    add bp, 4

    NewLine

    cmp bp, 80
    jnz C

    ret
Print endp

code ends
end main

【问题讨论】:

  • Enter 不是一个特别好的命名选择,因为有一条同名的 x86 指令。您确定汇编器确实扩展了您的宏而不是为enter 指令生成操作码吗? (即您是否查看过程序的反汇编?)
  • 我不知道有一个'enter'指令,我重命名了宏但问题仍然在这里。
  • 使用调试器单步执行代码。

标签: sorting assembly average procedure x86-16


【解决方案1】:

问题在于这两行(其他地方可能类似):

mov array[bp], ax
mov array[bp+2], dx

默认情况下,bp 寄存器寻址stack 段,而不是array 所在的data 段。您必须使用另一个索引寄存器,或者使用

覆盖该段
mov ds:array[bp], ax
mov ds:array[bp+2], dx

如果它与少量元素一起工作,那是幸运的,没有任何损坏导致崩溃或破坏数据。

更新

我建议修改GetNum proc,以便您可以使用bx 来索引array,而不是bp

proc GetNum  
mov bx, 0
mov ch, 20

NextNumber:
push bx
NewLine
...
pop bx
mov array[bx], ax
mov array[bx+2], dx
add bx, 4 
...

与您的排序功能类似 - 交换 bxbp 的角色。最好使用bp 作为通用寄存器,bx 作为索引寄存器。

【讨论】:

  • 不要使用 BP 作为数据变量的指针(正如 Weather 所说)。顺便说一句,将堆栈从 DD 更改为 DW 对我来说是一个非常有趣的发现。
  • @Asnira Jose 很厚脸皮:堆栈没有这样的类型。您的意思是您将array DD 更改为array DW。这是错误的:你需要 20 * 4 字节来存储你的数据。要使用DW,您必须声明 40 个元素而不是 20 个,因为您为每个元素存储 32 位值。
  • @Asnira 很遗憾您没有找到解决此问题的正确方法。这次你已经捏造了出来,但你还没有学会正确的方法。下一次,你装备好点了吗?我已经用一些建议更新了我的答案。
  • 您最终将使用bp 作为索引寄存器。它的典型用途是索引堆栈帧,但这与“借用”堆栈底部完全不同!这就是bp 的默认段是stack 段的原因。
  • 有很多材料可供好奇的人使用,要想编程好,你必须做到这一点。这是关于堆栈帧的一个 SO 问题,还有其他问题! stackoverflow.com/questions/579262/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-18
  • 2014-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多