如何在汇编语言中按ASCII码升序排序4个可变长度单词?
问题描述
我有4个单词(每个单词长度为1-4个字符),需要按ASCII码对它们进行升序排序,例如输入{'1234','abcd','123','e'},排序后结果应为{'e','123','1234','abcd'}。我编写了一段汇编代码,但冒泡排序部分尚未完成,尝试多种方法后仍无法实现,恳请帮忙完善代码。以下是我的代码:
DOSSEG .MODEL SMALL .STACK 32 .DATA NUMERE DB 0Dh,0Ah,'Nr.(1)=$' KBD DB 5,0,0,0,0,0,0 STORE DB 4 DUP (20h,20h,20h,20h) .CODE START: MOV AX,@DATA MOV DS, AX MOV CX, 4 MOV DI, (OFFSET STORE) + 4 AGAIN: PUSH CX ; afisare sir de interogare MOV DX, OFFSET NUMERE MOV AH, 9 INT 21h INC [NUMERE+6] MOV [KBD+1], 0 ; se citeste un numar cu max. 4 cifre MOV AH, 0Ah MOV DX, OFFSET KBD INT 21h MOV CL, [KBD+1] MOV CH, 0 MOV SI, (OFFSET KBD) + 2 PUSH DI SUB DI, CX NEXT: MOV AL, [SI] MOV [DI], AL INC SI INC DI LOOP NEXT POP DI ADD DI, 4 POP CX LOOP AGAIN ;bubble sort starts MOV CX, 3 SORT: PUSH CX MOV CX,3 MOV SI, OFFSET STORE MOV DI, OFFSET STORE+4 INNER_LOOP: MOV AX, [DI] CMP [SI], AX JNG NO_SWAP SWAP: NO_SWAP: INC SI INC DI LOOP INNER_LOOP INC SI POP CX LOOP SORT ;bubble sort ends MOV SI, OFFSET STORE MOV CX, 4 DISP: CALL CRLF PUSH CX MOV CX,4 NUM:MOV AH, 2 MOV DL, [SI] INT 21h INC SI LOOP NUM POP CX LOOP DISP MOV AH, 4CH INT 21H CRLF:MOV AH,2 MOV DL,0Ah INT 21h MOV AH,2 MOV DL,0Dh INT 21h RET END START
完善后的代码
下面是修复了冒泡排序逻辑的完整代码:
DOSSEG .MODEL SMALL .STACK 32 .DATA NUMERE DB 0Dh,0Ah,'Nr.(1)=$' KBD DB 5,0,0,0,0,0,0 STORE DB 4 DUP (20h,20h,20h,20h) ; 每个单词占4字节,不足补空格 .CODE START: MOV AX,@DATA MOV DS, AX MOV CX, 4 MOV DI, (OFFSET STORE) + 4 AGAIN: PUSH CX ; 显示提示信息 MOV DX, OFFSET NUMERE MOV AH, 9 INT 21h INC [NUMERE+6] ; 更新提示中的数字(1→2→3→4) MOV [KBD+1], 0 ; 重置输入长度 MOV AH, 0Ah MOV DX, OFFSET KBD INT 21h ; 调用DOS输入函数 MOV CL, [KBD+1] MOV CH, 0 MOV SI, (OFFSET KBD) + 2 PUSH DI SUB DI, CX ; 定位到当前单词的起始位置(从后往前填) NEXT: MOV AL, [SI] MOV [DI], AL INC SI INC DI LOOP NEXT POP DI ADD DI, 4 ; 移动到下一个单词的起始位置 POP CX LOOP AGAIN ; 冒泡排序开始 MOV CX, 3 ; 外层循环:4个元素需3轮排序 SORT: PUSH CX MOV CX, 3 ; 内层循环:每轮比较次数递减,初始3次 MOV SI, OFFSET STORE MOV DI, OFFSET STORE + 4 INNER_LOOP: ; 完整比较两个4字节的单词(按ASCII升序,空格ASCII值小于数字/字母) MOV AX, [SI] CMP AX, [DI] JLE SKIP_SWAP ; 前两个字节小于等于,继续比较后两个 JMP NEED_SWAP MOV AX, [SI+2] CMP AX, [DI+2] JLE SKIP_SWAP NEED_SWAP: ; 交换两个4字节的单词 MOV AX, [SI] XCHG AX, [DI] MOV [SI], AX MOV AX, [SI+2] XCHG AX, [DI+2] MOV [SI+2], AX SKIP_SWAP: ADD SI, 4 ; 移动到下一个单词的起始 ADD DI, 4 LOOP INNER_LOOP POP CX LOOP SORT ; 冒泡排序结束 ; 输出排序后的结果 MOV SI, OFFSET STORE MOV CX, 4 DISP: CALL CRLF PUSH CX MOV CX,4 NUM:MOV AH, 2 MOV DL, [SI] INT 21h INC SI LOOP NUM POP CX LOOP DISP MOV AH, 4CH INT 21H CRLF:MOV AH,2 MOV DL,0Ah INT 21h MOV AH,2 MOV DL,0Dh INT 21h RET END START
关键修改说明
- 完整单词比较:原代码仅比较了每个单词的前2字节,现在改为分两次比较4字节(AX寄存器是16位,每次处理2字节),确保整个单词的ASCII顺序正确。
- 实现交换逻辑:添加了
NEED_SWAP标签下的交换代码,通过XCHG指令交换两个单词的4字节内容。 - 修正指针移动:内层循环中,每次比较后需要将SI和DI各加4(而非加1),因为每个单词占4字节,这样才能定位到下一个单词的起始位置。
- 调整循环条件:移除了原代码中多余的
INC SI,避免指针越界。
内容的提问来源于stack exchange,提问作者Samuel Edi
相关产品推荐
相关产品推荐

