【问题标题】:Assembly A86 - Bubble Sort装配 A86 - 冒泡排序
【发布时间】:2015-03-17 17:08:57
【问题描述】:

我正在编写一个汇编程序来接收一串字符,使用冒泡排序对它们进行排序,然后输出排序后的字符串。我无权使用调试器,这就是我不得不寻求帮助的原因。我的程序似乎陷入了 BSORT 子例程中的无限循环,我似乎无法找到导致它的原因。这是一个作业,所以我宁愿解释我哪里出错了/我做错了什么,而不是仅仅得到解决方案。

这是我的代码:

TITLE   BSORT   
PAGE    60, 132

;   This program gets a string of input
;   and sorts it by ASCII value, then outputs
;   the sorted string to the monitor
;
;   Define constants
;
CR  EQU     0DH     ;define carriage return
LF  EQU     0AH     ;define line feed
EOM EQU     '$'     ;define end of message marker
NULL    EQU     00H     ;define NULL byte
;
;   Define variables
;
JMP START
PROMPT  DB      CR, LF, "Enter a string of characters (max 100): ", EOM
INBUF   DB      100, ?, 100 DUP ?
MESSAGE DB      CR, LF, "The sorted string is: ", CR, LF, CR, LF, EOM
;
;
;   Program Code
;           
;   
BSORT:  
;|——————————
;| CX holds count
;| SI points to first item
;|____________

    MOV BX, CX      ;BX will be inner loop variable
    DEC BX      ;last value will be EOM marker

OUTER:  DEC CX
    JZ  DONE        ;when the count is zero, we’re done

    XOR DL, DL      ;DL (hasSwapped) = false
    MOV SI, DI      ;reset SI

INNER:  MOV AX, [SI]    ;load 2 characters
    CMP AL, AH      ;first char is in AL, second is AH
    JBE NOSWAP      ;if AL <= AH, no swap needed
    MOV DL, 1       ;else, hasSwapped = true
    XCHG    AL, AH      ;swap first and second chars
    MOV [SI], AX    ;put swapped chars back in string

NOSWAP: INC SI      ;next chars
    CMP SI, BX
    JL  INNER
    TEST    DL, DL      ;else, did we swap?
    JNZ OUTER       ;if yes, loop again

DONE:   RET         ;if done, return to main program
;End subroutine

READ MACRO
 MOV     AH, 0AH
 LEA     DX, #1
 INT     21H
 #EM


WRITE MACRO
 MOV     AH, 09H
 LEA     DX, #1
 INT     21H
 #EM
;
;main
START:  WRITE PROMPT
        READ INBUF

        LEA SI, INBUF+2 ;point SI to beginning of array
        MOV CX, SI      ;save SI in the CX register
        ADD CL, B[SI-1] ;add the count that the OS records to the CL register
        ADC CH, 0       ;if carry, add to upper bits
        MOV SI, CX      ;move back to SI and see what it points to
        MOV B[SI], '$'  ;replace carriage return with end of text marker
        MOV CX, SI  ;put count in CX

        LEA SI, INBUF+2 ;point SI to beginning of array
        LEA DI, INBUF+2 ;copy of beginning of array 
        CALL BSORT

        WRITE MESSAGE
        WRITE [INBUF+2]

        MOV AX, 2C00H
        INT 21H ;return control to OS
;
;   Program End
;
        END START

当它运行时,它会打印提示并接收字符串而没有明显的问题,但它永远不会打印消息或排序的字符串。以前,我让它打印消息和字符串(不知道我改变了什么让它停止),但它没有完全排序。

非常感谢任何帮助/指导。

编辑 1:好的,好消息是,我在导致无限循环的循环中发现了我的问题(我认为)。但是排序没有发生,现在我也得到了一些非常有趣的输出。这是运行时的输出:

有什么想法吗?

编辑 2:正在排序! :D

但是,它仍然在我的字符串开头插入一个小写的 d 和黑桃字符。一旦我找到它的来源,我想它会解决的!以上代码已更新。

这是我现在的输出:

编辑 3:找到我的奇怪字符 - 我正在打印所有 [INBUF],而不仅仅是字符串 [INBUF+2]。谢谢你们的帮助! :)

【问题讨论】:

  • 我没有调试器的访问权限 ...你安装一个怎么样?
  • @Jester - 很高兴,您知道我可以在 DosBox 中运行与 A86 一起使用的调试器吗?我没有任何运气找到一个有效的。
  • dosbox 本身有一个内置的调试器。至于在 dosbox 中运行调试器,我想到的是 turbo 调试器。
  • @Jester - 谢谢你的建议!我会研究一下,看看我能不能让一个工作!
  • Eric Isaacson 的 D86 应该可以工作,不是吗?

标签: sorting assembly x86 bubble-sort a86


【解决方案1】:

我相信你不会重置 SI 寄存器。在完成内循环的第一次迭代后,SI 永远不会小于或等于 BX。看看是不是这个问题。

MOV BX, CX              ;BX will be inner loop variable

OUTER:  DEC CX
JZ  DONE                ;when the count is zero, we’re done

XOR DL, DL              ;DL (hasSwapped) = false
                        ;You should see if resetting SI here will solve the infinite loop.

INNER:  MOV AX, [SI]    ;load 2 characters
                        ;What happens in the second iteration ?
CMP AL, AH              ;first char is in AL, second is AH
JBE NOSWAP              ;if AL <= AH, no swap needed
MOV DL, 1               ;else, hasSwapped = true
XCHG    AL, AH          ;swap first and second chars
MOV [SI], AX            ;put swapped chars back in string

NOSWAP: INC SI          ;next chars
CMP SI, BX              ;In the first iteration of the inner loop that should be ok.
JLE INNER
                        ;At this point SI kept its value
TEST    DL, DL          ;else, did we swap?
JNZ OUTER               ;if yes, loop again

【讨论】:

  • 感谢您的建议。在进入循环之前,我将 SI 的原始值的副本保存在 DI 中(应该是字符串的开头),然后在清除 DL 后将 DI 移动到 SI 中,以重置 SI。但现在它完全清除了我的字符串,打印出来的“排序字符串”始终是字母 d 和 ASCII 代码 6(黑桃花色)。这个逻辑有问题吗?
  • 好吧,至少解决了无限循环:)。我需要提醒自己冒泡排序是如何工作的。
猜你喜欢
  • 2012-07-14
  • 1970-01-01
  • 1970-01-01
  • 2013-10-09
  • 2015-09-12
  • 1970-01-01
  • 2014-03-26
  • 2015-03-06
相关资源
最近更新 更多