题目:
StringA和StringB是两个串(可以程序固定,也可以由用户输入)。打印一个菜单供用户选择:
; multi-segment executable file template.
data segment
; add your data here!
StringA db 'AbcdreStrdfjoStr$'
StringB db 'Str$'
StringBLength db 0
StringALength db 0
StringACurrentIndex dw 0
StringBCurrentIndex dw 0
insertIndexString db 8 dup('$')
inputInsertStringTips db 'Please Input a index that you want to insert from B to A : $'
insertIndex db 0;
menuMsg db 'Please choose operation:','$'
option1Msg db '1. search StringB from StringA,','$'
option2MSg db '2. insert StringB to StringA special place,','$'
option3Msg db '3. delete all StringB in StringA','$'
enterChoiceMsg db 'Please Input Choice from 1 to 3: ','$'
invalidChoiceMsg db 'invalid choice,please reinput','$'
inputPostitionMsg db 'Please input the place you want to insert: ','$'
resultMsg db 'result: ','$'
resultArray db 10 dup(0)
notFoundMsg db 'StringB not found in StringA!','$'
newline db 0ah,0dh,'$'
matchArray db 10 dup(0)
matchNum db 0;
ends
stack segment
dw 128 dup(0)
ends
code segment
;在 StringA 中删除 StringB
deleteStringBInStringA proc
;环境变量保护
push ax;
push bx;
push cx;
push dx;
push si;
push di;
; 遍历字符串 A
lea si, StringA
;需要定义一个循环变量来记录 StringA 遍历的位置一遍和si做加法的到index
traversalDeleteStringA:
mov al, [si]
lea di, StringB
traversalDeleteStringB:
mov bl, [di]
xor cx, cx
cmp al, '$'
je returnToMainProFromDelete
jmp deleteLoopInStringB
notDeleteMatch:
sub si, cx
cmp cx, 0
je outputOnce
outputNotMatch:
mov dl, [si]
mov ah,02h
int 21h
inc si
cmp cl, 1
je normalProgram
loop outputNotMatch
outputOnce:
mov al, [si]
mov dl, [si]
mov ah, 02h
int 21h
normalProgram:
inc si
lea di, StringB
mov al, [si]
mov bl, [di]
cmp al, '$'
je returnToMainProFromdelete
jmp deleteLoopInStringB
deleteLoopInStringB:
cmp bl, '$'
je deleteMatchStringB
cmp al, bl
jne notDeleteMatch
inc si
inc di
inc cl
mov al, [si]
mov bl, [di]
jmp deleteLoopInStringB
deleteMatchStringB:
lea di, StringB
mov al, [si]
jmp traversalDeleteStringB
returnToMainProFromdelete:
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
deleteStringBInStringA ENDP
insertStringBToStringA PROC
; 用户把 StringB 插入到 StringA 的特定位置
; 状态保存
push ax
push bx
push cx
push dx
push si
push di
lea dx, newline
mov ah, 09h
int 21h
lea dx, resultMsg
mov ah, 09h
int 21h
; 思路: 一个寄存器存储该插入位置的地址,当到达那个位置的时候,开始打印 StringB 打印完StringB 后继续打印StringA
lea si, StringA;
xor cx, cx
mov cl, [insertIndex];
add cx, si;
traversalOutputStringA:
mov al, [si]
cmp al, '$'
je returnToMainProFromInsert
cmp si, cx
je outputStringB:
outputStringA:
mov dl, al,
mov ah, 02h
int 21h
inc si
jmp traversalOutputStringA
outputStringB:
lea di, StringB
innerOutputStringBLoop:
mov bl, [di]
cmp bl, '$'
je outputStringA
mov dl, bl
mov ah, 02h
int 21h
inc di
jmp innerOutputStringBLoop
returnToMainProFromInsert:
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
insertStringBToStringA ENDP
printNumber PROC ; 子程序用于打印十进制数字
;要打印的数字存储在 ax 中
push ax ; 保存寄存器状态
push bx
push cx
push dx
mov bx, ax ; 因为要打印换行以及结果提示暂存 数字至 bx
lea dx, newline
mov ah, 09h
int 21h
lea dx, resultMsg
mov ah, 09h
int 21h
mov ax, bx
mov bx, 10 ; BX = 10
xor cx, cx ; CX = 0,用于计数
NumLoop:
xor dx, dx ; DX = 0
div bx ; AX = AX / BX, DX = AX % BX
push dx ; 将余数压栈
inc cx ; 增加计数
test ax, ax ; 检查商是否为0
jnz NumLoop ; 如果不为0,继续循环
PrintLoop:
pop dx ; 弹出栈顶元素到 DX
add dl, '0' ; 将数字转换为字符
mov ah, 2 ; AH = 2,用于显示单个字符
int 21h ; 输出字符
loop PrintLoop ; 循环打印数字
lea dx, newline
mov ah, 09h
int 21h
pop dx ; 恢复寄存器状态
pop cx
pop bx
pop ax
ret
printNumber ENDP
findAdnPrintIndices proc
;环境变量保护
push ax;
push bx;
push cx;
push dx;
push si;
push di;
; 遍历字符串 A
lea si, StringA
;需要定义一个循环变量来记录 StringA 遍历的位置一遍和si做加法的到index
traversalStringA:
mov al, [si]
lea di, StringB
traversalStringB:
mov bl, [di]
cmp al, '$'
je returnToMainProFromFindIndices
jmp loopInStringB
notMatch:
inc si
lea di, StringB
mov al, [si]
mov bl, [di]
cmp al, '$'
je returnToMainProFromFindIndices
jmp loopInStringB
loopInStringB:
cmp bl, '$'
je MatchStringB
cmp al, bl
jne notMatch
inc si
inc di
mov al, [si]
mov bl, [di]
jmp loopInStringB
MatchStringB:
;计算当前的索引值并且打印,此时要注意保存 al 里面的值以及si 当前的值
mov [StringACurrentIndex], si;
lea si, StringA
mov ax, [StringACurrentIndex]
sub ax, si
sub ax, 3
call printNumber
mov si, [StringACurrentIndex]
mov al, [si]
;把di变量重新复制然后到 tranvelsalStringB循环里面去
lea di, StringB
jmp traversalStringB
returnToMainProFromFindIndices:
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
findAdnPrintIndices ENDP
start:
; set segment registers:
mov ax, data
mov ds, ax
mov es, ax
; 计算每一个字符串的长度
lea si, StringA
calcStringALength:
mov al, [si]
cmp al, '$'
je calcStringBLength
mov bl, [StringALength]
inc bl
inc si
mov [StringALength], bl
jmp calcStringALength
calcStringBLength:
lea si, StringB
calcStringBLengthLoop:
mov al, [si]
cmp al, '$'
je printMenu
mov bl, [StringBLength]
inc bl
inc si
mov [StringBLength], bl
jmp calcStringBLengthLoop
; add your code here
; print menu
printMenu:
mov ah, 09h
lea dx, menuMsg
int 21h
lea dx, newline
int 21h
; print option1
mov ah, 09h
lea dx, option1Msg
int 21h
lea dx, newline
int 21h
;print option2
mov ah, 09h
lea dx, option2Msg
int 21h
lea dx, newline
int 21h
;print option3
mov ah, 09h
lea dx, option3Msg
int 21h
lea dx, newline
int 21h
lea dx, newline
int 21h
; notice user to input choice
lea dx, enterChoiceMsg
int 21h
; get user input
mov ah, 01h
int 21h
sub al, '0'
cmp al, 1
je option1
cmp al, 2
je option2
cmp al, 3
je option3
; if the input choices are all invalid end program
lea dx, newline
mov ah, 09h
int 21h
lea dx, invalidChoiceMsg
int 21h
jmp endProgram
option1:
; newline to get beautiful screen
mov ah, 09h
lea dx, newline
int 21h
;search StringB's place in StringA
call findAdnPrintIndices
lea dx, newline
mov ah, 09h
int 21h
jmp endProgram
option2:
mov ah, 09h
lea dx, newline
int 21h
; 输入要插入的位置 insertIndex
; 思路: 通过得到要插入的位置,逐个输出 StringA 然后到达要插入的位置的时候 输出 StringB 然后接着输出 StringA
lea dx, inputInsertStringTips
mov ah, 09h
int 21h
lea dx, insertIndexString
mov ah, 0ah
int 21h
lea si, insertIndexString;
; 清空 cx
xor cx, cx
; 把输入的字符串转为数字
inc si;
mov cl, [si]
inc si;
; 清空 ax 的值
xor ax, ax
mov al, 0;
mov dl, 10
getNumberLoop:
mov bl, [si]
sub bl, '0'
mul dl
add al, bl
inc si;
loop getNumberLoop;
mov bl, [StringALength]
cmp al,bl
jg endProgram
mov [insertIndex], al;
call insertStringBToStringA;
jmp endProgram
option3:
mov ah, 09h
lea dx, newline
int 21h
mov ah, 09h
lea dx, resultMsg
int 21h
call deleteStringBInStringA
lea dx, newline
int 21h
jmp endProgram
endProgram:
mov ah, 4ch
int 21h
ends
end start ; set entry point and stop the assembler.
printNumber PROC ; 子程序用于打印十进制数字
push ax ; 保存寄存器状态
push bx
push cx
push dx
mov bx, 10 ; BX = 10
xor cx, cx ; CX = 0,用于计数
NumLoop:
xor dx, dx ; DX = 0
div bx ; AX = AX / BX, DX = AX % BX
push dx ; 将余数压栈
inc cx ; 增加计数
test ax, ax ; 检查商是否为0
jnz NumLoop ; 如果不为0,继续循环
PrintLoop:
pop dx ; 弹出栈顶元素到 DX
add dl, '0' ; 将数字转换为字符
mov ah, 2 ; AH = 2,用于显示单个字符
int 21h ; 输出字符
loop PrintLoop ; 循环打印数字
pop dx ; 恢复寄存器状态
pop cx
pop bx
pop ax
ret
printNumber ENDP
; multi-segment executable file template.
data segment
; add your data here!
pkey db "PeaseInput the insert Index : $"
insertIndex db 7 dup('$')
ends
stack segment
dw 128 dup(0)
ends
code segment
start:
; set segment registers:
mov ax, data
mov ds, ax
mov es, ax
; add your code here
lea dx, pkey
mov ah, 9
int 21h ; output string at ds:dx
; wait for any key....
lea dx, insertIndex;
mov ah, 0ah;
int 21h
lea si, insertIndex;
; 清空 cx
xor cx, cx
; 把输入的字符串转为数字
inc si;
mov cl, [si]
inc si;
; 清空 ax 的值
xor ax, ax
mov al, 0;
mov dl, 10
getNumberLoop:
mov bl, [si]
sub bl, '0'
mul dl
add al, bl
inc si;
loop getNumberLoop;
mov ax, 4c00h ; exit to operating system.
int 21h
ends
end start ; set entry point and stop the assembler.