2024-06-25 10:22:46
; 从键盘输入N+1个数,对前N个数进行选择排序,再用折半查找判断第N+1个数是否在前N个数中,输出结果。
; 输入数据最大为16位
CODE SEGMENT
ASSUME CS:CODE
START: PUSH CS
POP DS
PUSH CS
POP ES
CALL INPUTNUM
LEA DI,@ARRAY
MOV CX,@NUM
DEC CX
CALL SELECTSORT
MOV AH,2
MOV DL,13
INT 21H
MOV DL,10
INT 21H
LEA SI,@ARRAY
MOV CX,@NUM
DEC CX
CMP CX,0
JZ @EXIT
CLD
@1:
LODSW
CALL DSPAXS
LOOP @1
MOV AH,2
MOV DL,13
INT 21H
MOV DL,10
INT 21H
LEA SI,@ARRAY
MOV CX,@NUM
DEC CX
MOV BX,CX
SHL BX,1
ADD BX,SI
CALL FIND
CALL DSPAXS
@EXIT:
MOV AH,4CH
INT 21H
;==============================================================
; 查找的 元素地址 在 bx,数组首地址 为 si , 元素个数为 cx
; 若找到 ax=找到的序号(从0开始), 否则 ax=-1 (FFFF)
FIND PROC NEAR
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSHF
MOV @X0_F,0
MOV @X1_F, CX
DEC WORD PTR @X1_F
MOV AX,@X0_F
SHL AX,1
ADD AX,SI
MOV DI,AX
MOV AX,[DI]
MOV @Y0_F,AX
MOV AX,@X1_F
SHL AX,1
ADD AX,SI
MOV DI,AX
MOV AX,[DI]
MOV @Y1_F,AX
@FIND0:
MOV AX,@X1_F
SUB AX,@X0_F
CMP AX,1
JL @FINDORNO1
JE @FINDORNO2
MOV AX,@X0_F
ADD AX,@X1_F
SHR AX,1
MOV @XX_F,AX
SHL AX,1
ADD AX,SI
MOV DI,AX
MOV AX,[DI]
MOV @YY_F,AX
MOV DX,@YY_F
MOV AX,@XX_F ;======
CMP [BX],DX
JE @FINDEXIT
JG @FIND1
MOV AX,@XX_F
MOV @X0_F,AX
MOV AX,@YY_F
MOV @Y0_F,AX
JMP @FIND0
@FIND1:
MOV AX,@XX_F
MOV @X1_F,AX
MOV AX,@YY_F
MOV @Y1_F,AX
JMP @FIND0
@FINDEXIT:
POPF
POP DI
POP SI
POP DX
POP CX
POP BX
RET
@FINDORNO1:
MOV AX,@X0_F
MOV DX,@Y0_F
CMP [BX],DX
JE @FINDEXIT
MOV AX,-1
JMP @FINDEXIT
@FINDORNO2:
MOV AX,@X0_F
MOV DX,@Y0_F
CMP [BX],DX
JE @FINDEXIT
MOV AX,@X1_F
MOV DX,@Y1_F
CMP [BX],DX
JE @FINDEXIT
MOV AX,-1
JMP @FINDEXIT
@X0_F DW 0
@X1_F DW 0
@XX_F DW 0
@Y0_F DW 0
@Y1_F DW 0
@YY_F DW 0
FIND ENDP
;===============================================================
; 键盘输入数值数组子程序(数组名为@array,元素个数存放在@num中)
; 可以是负数
; 采用字符串缓冲输入,避免原来键入后不能回退修改的问题 !
INPUTNUM PROC NEAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSHF
; 对数组@array清零
MOV CX,100
MOV AX,0
LEA DI,@ARRAY
REP STOSW
MOV WORD PTR @NUM,0
; 输入的数据以一个空格分隔,以回车符结束输入
LEA DX,@STRA
MOV AH,10
INT 21H
MOV CL,@STRN
MOV CH,0
MOV WORD PTR @STRM,CX
LEA SI,@STR
CLD
LEA DI,@ARRAY
MOV WORD PTR @NUM,0
@STIN:
MOV AX,0
PUSH AX
MOV BYTE PTR @SIGNN,0
@AGAIN1:
CMP WORD PTR @STRM,0
JE @LINE0
LODSB
DEC WORD PTR @STRM
CMP AL,' '
JE @LINE0
CMP AL,'-'
JNE @INPUT1
MOV BYTE PTR @SIGNN,1
JMP @AGAIN1
@INPUT1:
SUB AL,30H
MOV AH,0
MOV BX,AX
POP AX
MOV CL,10
MOV CH,0
MUL CX
ADD AX,BX
PUSH AX
JMP @AGAIN1
@LINE0:
POP AX
CMP BYTE PTR @SIGNN,1
JNE @INPUT2
NEG AX
@INPUT2:
MOV WORD PTR[DI],AX
INC WORD PTR @NUM
CMP WORD PTR @STRM,0
JE @STINEND
INC DI
INC DI
JMP @STIN
@STINEND:
POPF
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
RET
@STRA DB 255
@STRN DB ?
@STR DB 255 DUP(?)
@STRM DW 0
@ARRAY DW 100 DUP(0)
@NUM DW 0
@CHAR DB ?
@SIGNN DB 0
INPUTNUM ENDP
;=========================================
SELECTSORT PROC NEAR
; 数组起始地址 存入 di,元素个数 存入 cx
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSHF
CMP CX,1
JE @@SELE5
DEC CX ; ################
MOV BX,0
@@SELE1:
PUSH CX
MOV SI,DI
INC SI
INC SI ; {SI=DI+2}
PUSH DI ;{保存DI }
MOV AX,[DI][BX] ; {假设MAX 为第一个}
@@SELE2: MOV DX,[SI][BX] ; {存储器到寄存器,节省时间}
CMP AX,DX
JGE @@SELE3 ; 从大到小,有符号数排序 #################
MOV DI,SI ; {小于时,将SI替换DI,即将J替换I, 保存MAXI}
MOV AX,DX ; {保存MAX 到AX}
@@SELE3: INC SI
INC SI
LOOP @@SELE2
MOV SI,DI ; {还原SI,即将I替换J}
POP DI ; {取出栈中保存的I}
CMP DI,SI ; {与J 比较}
JE @@SELE4 ; {相同时不交换}
MOV AX,[DI][BX] ; {在内循环之外交换}
XCHG AX,[SI][BX]
MOV [DI][BX],AX
@@SELE4: INC BX
INC BX
POP CX
LOOP @@SELE1
@@SELE5:
POPF
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
RET
SELECTSORT ENDP
;==================================
; 输出有符号数,输出的数应放 ax中
DSPAXS PROC NEAR
PUSH AX
OR AX,AX
JNS @DSPAXS
NEG AX
PUSH AX
PUSH DX
MOV AH,2
MOV DL,'-'
INT 21H
POP DX
POP AX
@DSPAXS:
CALL DSPAX
POP AX
RET
DSPAXS ENDP
;===============================
DSPAX PROC NEAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSHF
XOR CX,CX
MOV BX,10
@DSPAX1:
XOR DX,DX
DIV BX
INC CX
OR DX,30H
PUSH DX
CMP AX,0
JNE @DSPAX1
MOV AH,2
@DISPAX2:
POP DX
INT 21H
LOOP @DISPAX2
MOV DL,32
INT 21H
POPF
POP DX
POP CX
POP BX
POP AX
RET
DSPAX ENDP
;================================
CODE ENDS
END START