汇编实验4-1

2023-12-27 17:19:34

汇编实验4-1

题目:
StringA和StringB是两个串(可以程序固定,也可以由用户输入)。打印一个菜单供用户选择:

  • 选项1:在StringA中查找StringB的所在的位置,打印其位置下标(从0开始)。如果包含多个
    ,需要逐一打印。
  • 选项2:在StringA中指定位置插入StringB,打印插入后的串。指定位置可以固定,也可以由用
    户输入(需要进行边界判定)。
  • 选项3:在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.

知识点

打印一个数字0 ~ 2^16

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.

文章来源:https://blog.csdn.net/Go_ahead_forever/article/details/135246733
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。