我在程序集8086中需要一个程序
输入:一句话(字符串) 输出:逐字逐句排序或按用户希望降序请帮助
答案 0 :(得分:0)
由于您要求提供家庭作业帮助,因此最好关注算法而不是代码。
我假设你是在DOS环境下编程,如果不是这样,只需将概念翻译成你的操作系统。
您需要做的第一件事就是要求用户输入。在DOS中有几种方法可以做到这一点,根据您的需要,您必须选择最适合的方法。我认为缓冲输入是最好的选择,使用INT 21/AH=0ah
。您可以使用Ralph Brown Interrupt List的在线版本作为参考。
你有一个带有输入字符串的缓冲区,你需要扫描它并识别单词。单词由特定字符分隔,让我们假设只有一个空格(ASCII代码20h)字符用作单词分隔符。您不能假设在两个连续的单词之间只出现一个空格
识别单词的开头和结尾很容易,但是一旦你开始和结束,你如何保存一个单词?
单词是字符串,字符串的问题是它们具有可变长度,因此您无法将它们复制到固定大小的缓冲区中,因为您必须交换它们才能对需要使用间接层的单词进行排序。
不是从输入字符串中复制单词,而是使用DOS字符串终止符$
(ASCII代码24h)终止每个单词,并将指针保存到它们的开头。这是概念的丑陋图片
现在你可以减少排序指向字符串数组的问题,这是一项简单的任务
首先需要一个字符串比较器,比如strcmp
,一个比较字符串A和B的函数,如果A<则返回-1。 B,如果A = B,则为0;如果A> B,则为1。 B.字符串上有许多命令,字典顺序是问题所针对的。您可以在互联网上找到有关此主题的教程
在比较器之后你需要一个排序算法,冒泡排序效率很低但很容易实现。这里的技巧是你比较字符串,但交换指针!
最后,您只需按照在数组中找到它们的顺序打印字符串。
我做了一个简单的DOS COM程序来解决你的问题。我警告你,你应该只使用它作为样本,它使用原始8086中没有的许多指令,并在堆栈上创建输入缓冲区和数组。无论如何这里是它的输出(在DOSBox中)和在源代码下面(对于NASM)
;COM binaries are loaded in a new segment starting at offset 100h
;The area between the start of the segment and the offset 100h is the PSP (Program segment prefix)
org 100h
;Data and code is in one section
section .text
start:
;Set the stack as far away as possible from the code but still in the same segment
mov ax, cs
mov ss, ax
xor sp, sp
;All other segment registers points to CS segment
push cs
pop ds
push es
pop ds
;Be sure DF is 0
cld
mov ah, 09h
mov dx, strInputSentence
int 21h
;Allocate space for 255 byte buffer (the max) but keep the SP aligned at WORD boundary
sub sp, 100h
push 00ffh ;Push the Buffer structure for INT 21/0ah
mov WORD [buffer], sp
;Get the input string
mov dx, sp
mov ah, 0ah
int 21h
;Reserve an array of 256 WORD
sub sp, 200h
mov WORD [tokens], sp
;Tokenize the string
mov bx, WORD [buffer]
movzx ax, BYTE [bx+01h] ;String length
add bx, 02h ;String start
push ax
push bx
push WORD [tokens] ;Output array
push 0ffh ;Max items in output array
call tokenize
mov WORD [tokens_num], ax ;Words found
test ax, ax
jz .no_words
call show_original
call show_ascending
call show_descending
jmp .end
.no_words:
mov ah, 09h
mov dx, strNoWords
int 21h
.end:
mov ax, 4c00h
int 21h
strInputSentence db "Please, type a sentence: ", 24h
buffer dw 0
tokens dw 0
tokens_num dw 0
strOriginalOrd db 0dh, 0ah, "Here are the words as typed: "
strCRLF db 0dh, 0ah, 24h
strNoWords db 0dh, 0ah, "No words typed!", 24h
strAscendingOrd db "Here are the words sorted in ascending order:", 0dh, 0ah, 24h
strDescendingOrd db "Here are the words sorted in descending order:", 0dh, 0ah, 24h
show_original:
mov dx, strOriginalOrd
mov ah, 09h
int 21h
mov si, WORD [tokens]
mov cx, WORD [tokens_num];
.orig_ord:
mov dx, WORD [si]
int 21h
mov dx, strCRLF
int 21h
add si, 02h
loop .orig_ord
ret
show_ascending:
mov dx, strAscendingOrd
mov ah, 09h
int 21h
push strcmp
push WORD [tokens]
push WORD [tokens_num]
call bubble_sort
mov si, WORD [tokens]
mov cx, WORD [tokens_num];
.asc_ord:
mov dx, WORD [si]
int 21h
mov dx, strCRLF
int 21h
add si, 02h
loop .asc_ord
ret
show_descending:
mov dx, strDescendingOrd
mov ah, 09h
int 21h
push stricmp
push WORD [tokens]
push WORD [tokens_num]
call bubble_sort
mov si, WORD [tokens]
mov cx, WORD [tokens_num];
.asc_ord:
mov dx, WORD [si]
int 21h
mov dx, strCRLF
int 21h
add si, 02h
loop .asc_ord
ret
;Number of char
;Sentence
;Array of pointers
;Array items
tokenize:
push bp
mov bp, sp
sub sp, 02h
push di
push es
push cx
push si
push bx
push dx
mov dx, WORD [bp+0ah]
mov cx, WORD [bp+04h]
mov di, WORD [bp+06h]
mov si, WORD [bp+08h]
xor bx, bx
mov BYTE [bp-02h], 00h ;Status, 0 = Looking for a word start, 1 = Looking for word end
;DX = Character left to parse
;CX = Entries available in output array
;DI = Ptr to Output array current entry
;SI = Ptr to current char in input string
;BX = Words found
.look_for:
test cx, cx
jz .end
test dx, dx
jz .end
lodsb
dec dx
; char is 20h Status
; 0 0 found start
; 0 1 jump back
; 1 0 jump back
; 1 1 found end
cmp al, 20h
sete ah
xor ah, BYTE [bp-02h]
jnz .look_for
;Change status (0->1, 1->0)
mov ah, BYTE [bp-02h]
not ah
and ah, 01h
mov BYTE [bp-02h], ah
jnz .found_start
;Found word end
mov BYTE [si-01h], 24h ;24h terminate the word
jmp .look_for
.found_start:
;Found word start
lea ax, [si-01h]
stosw ;Save the pointer to the word
dec cx ;Less available entries
inc bx ;One more word found
jmp .look_for
.end:
mov BYTE [si], 24h ;24h terminate last word
mov ax, bx
pop dx
pop bx
pop si
pop cx
pop es
pop di
add sp, 02h
pop bp
ret 08h
;string1
;string2
strcmp:
push bp
mov bp, sp
push si
push di
push bx
mov si, WORD [bp+06h]
mov di, WORD [bp+04h]
.compare:
lodsb
mov ah, BYTE [di]
inc di
;AH = String 2 char
;AL = String 1 char
;If String1 is ended, check the other string
cmp al, 24h
mov bl, ah ;Value to check as terminator
mov bh, 0ffh ;Return value if the other string is not ended
jz .strend
;If String2 is ended, check the other string
cmp ah, 24h
mov bl, al ;Value to check as terminator
mov bh, 01h ;Return value if the other string is not ended
jz .strend
;Compare
sub al, ah
jz .compare ;If equals, repeat
jmp .end ;Result is computed, just end
.preend:
xor al, al ;Equals
.end:
pop bx
pop di
pop si
pop bp
ret 04h
.strend:
cmp bl, 24h ;Other string is ended, too?
jz .preend ;Success!
mov al, bh ;Return appropriate value
jmp .end
;Like strcmp but negated
stricmp:
push bp
mov bp, sp
push WORD [bp+06h]
push WORD [bp+04h]
call strcmp
neg al
pop bp
ret 04h
;comparer
;array
;elements
bubble_sort:
push bp
mov bp, sp
sub sp, 02h
pusha
cmp WORD [bp+04h], 2 ;Less than 2 element -> Already ordered
jb .end
mov di, WORD [bp+08h] ;Comparer
.cycle:
mov BYTE [bp-02h], 00h ;No swap done
mov cx, WORD [bp+04h] ;Elements in array
mov si, WORD [bp+06h] ;Array
dec cx ;Elements are compared in pairs
.sort:
lodsw
push ax
lodsw
push ax
call di ;Compare current and next string
sub si, 02h ;Get back to next string
cmp al, 00h
jg .swap ;If current > next, swap
.continue:
dec cx ;Elements left to compare
jnz .sort
;If no swap, the array is sorted
cmp BYTE [bp-02h], 00h
jne .cycle
jmp .end
.swap:
;Naive swap
mov ax, WORD [si-02h]
mov bx, WORD [si]
mov WORD [si], ax
mov WORD [si-02h], bx
;At least one swap done
mov BYTE [bp-02h], 01h
jmp .continue
.end:
popa
add sp, 02h
pop bp
ret 06h