组装 - 用于排序字符串的冒泡排序

Posted

技术标签:

【中文标题】组装 - 用于排序字符串的冒泡排序【英文标题】:Assembly - bubble sort for sorting string 【发布时间】:2014-12-06 17:20:27 【问题描述】:

我正在使用 tasm 编写一个汇编程序。我的任务是编写一个程序,该程序将使用冒泡排序按字母顺序对输入的字符串进行排序。前任。如果你输入“hello”,它应该写成“ehllo”。我已经写了输入字符串并对其进行排序的乞求(我认为它可以正常工作,直到它应该打印出结果的最后,但最后它只写了我的 .data 一次并完成了它的工作)PS 抱歉不好英文

.model small
.stack 100h

.data
request     db 'This program is using bubblesort to get alphabetical order of your enterd string', 0Dh, 0Ah, 'Enter your string:', 0Dh, 0Ah, '$'
result      db 0Dh, 0Ah, 'Result:', 0Dh, 0Ah, '$'
buffer      db 100, ?, 100 dup (0)

.code

start:
MOV ax, @data                   
MOV ds, ax                      


MOV ah, 09h
MOV dx, offset request
int 21h


MOV dx, offset buffer           
MOV ah, 0Ah                     
INT 21h                         


MOV si, offset buffer           
INC si                          
MOV bh, [si]                    
INC si                          

sort:
mov cx, [si] 
mov bx, [si]     

nextelement:
mov ax, [bx+si]     
cmp ax, [bx+si+1]   
jge noswap          
xchg ax, [bx+si+1]
mov ax, [bx+si]

noswap:
inc si              
cmp cx, si          
jl nextelement      
loop nextelement 



MOV ah, 09h
MOV dx, offset result
int 21h


char:
LODSB                           
MOV ah, 2                       
MOV dl, al                      
INT 21h                        

DEC bh                          
JZ ending                       
JMP char                        


ending:
MOV ax, 4c00h               
INT 21h                         

end start

【问题讨论】:

请注意,bh 寄存器与 bx 共享高 8 位,因此如果加载后者,前者也会被覆盖。 好吧,我以后会记住的 【参考方案1】:

1) 对于冒泡排序,您需要两个嵌套循环。外层循环重置内层循环的起始参数,直到没有东西可以交换。

2) 您对字符进行排序。那是 8 位值(字节)。您不能将它们直接加载到 16 位寄存器 (mov ax, [bx+si])。

3) [bx+si] & [bx+si+1]: 这太错误了,我无法解释错误:-)。

我没有更正您的代码,而是“从头开始”编写了一个示例:按照http://en.wikipedia.org/wiki/Bubble_sort 中的插图:

.MODEL small
.STACK 1000h                        ; Don't skimp with stack!

.DATA
    Struct0A EQU $                  ; Buffer for INT 21h/0Ah (max,got,buf)
        max db 100                  ; Maximum characters buffer can hold (incl. CR (0Dh))
        got db 0                    ; Number of characters actually read, (excl. CR (0Dh))
        buf db 100 dup (0)          ; Actual characters read, including the final carriage return (0Dh)
    Linefeed db 13, 10, '$'
    GetString   db 'Enter string: $'

.CODE
start:
    mov ax, @DATA                           ; Initialize DS
    mov ds, ax

    ; Input String
    mov ah, 09h
    mov dx, OFFSET GetString
    int 21h
    mov dx, OFFSET Struct0A
    mov ah, 0Ah
    INT 21h

    mov si, OFFSET buf                      ; Base for [si + bx] 
    xor bx, bx                              ; Prepare BX for following byte load
    mov bl, got                             ; Load length of string = 0Dh at the end
    mov BYTE PTR [si + bx], '$'             ; Delimiter for int 21h / 09h

    outer:
    dec bx                                  ; The last character is already at the right place
    jz done                                 ; No characters left = done
    mov cx, bx                              ; CX: loop variable
    mov si, OFFSET buf
    xor dl, dl                              ; DL (hasSwapped) = false

    inner:
    mov ax, [si]                            ; Load **two** characters
    cmp al, ah                              ; AL: 1. char, AH: 2. char
    jbe S1                                  ; AL <= AH - no change
    mov dl, 1                               ; hasSwapped = true
    xchg al, ah                             ; Swap characters
    mov [si], ax                            ; Store swapped characters
    S1:
    inc si                                  ; Next pair of characters
    loop inner

    test dl, dl                             ; hasSwapped == true?
    jnz outer                               ; yes: once more
    done:

    ; Print result
    mov dx, OFFSET Linefeed
    mov ah, 09h
    int 21h
    mov dx, OFFSET buf
    mov ah, 09h
    int 21h

    mov ax, 4C00h
    int 21h

END start

这是另一个“动画”插图:

https://www.youtube.com/watch?v=lyZQPjUT5B4

【讨论】:

非常感谢您的帮助。我了解冒泡排序的外观以及如何用其他语言对其进行编程,只是我真的不了解汇编程序。也感谢您花时间编写完整的程序:) 在某些 CPU 上,通过始终交换并使存储有条件来避免缓存行拆分/未对齐加载可能是一种胜利。例如mov al, [si]/rol ax,8/cmp/jbe。你甚至可以使用lodsb(但在比mov/inc慢的现代CPU上)。这会在 AX 上创建循环携带的依赖关系,但是如果需要大量交换,则 OTOH 会避免从存储到部分重叠负载的存储转发停顿。但是首先使用冒泡排序的唯一原因是紧凑的代码大小,而不是性能,所以我不会过多抱怨使用缓慢的 loop 指令。 @PeterCordes :如果定位 8086 rol ax, 8 不可用。 @PeterCordes : 如果你好奇当你推送一个立即数时 TASM 默认会发生什么,这是它生成的代码类型:push axpush bpmov bp, spmov word ptr [bp+2], 33h@987654340如果使用了指令push 33h,则会生成@。如果他们从不调试代码或生成列表文件,大多数人都不会意识到这一点。如果文件中没有指令或命令行上没有覆盖,TASM 将静默进行这些类型的转换,因为它默认为 8086 代码生成。 @PeterCordes :不确定是否有办法在 TASM 中关闭它。在使用 TASM 进行开发并针对实模式代码而不指定 .186 或更高版本时,我始终牢记这一点。另一方面,如果您在针对 8086 时尝试使用不受支持的指令而不是静默生成等效代码,则 MASM 将出错。

以上是关于组装 - 用于排序字符串的冒泡排序的主要内容,如果未能解决你的问题,请参考以下文章

js中sort()方法冒泡排序模拟

数组中冒泡排序直接选择排序反序排序原理与区别

C语言冒泡排序法

特么,冒泡排序有这么难?

特么,冒泡排序怎么可以这么难?

[PTA]7-30 字符串的冒泡排序