x86课程作业-第三次

第三次作业

一、
[要求] 使用函数表 完成乘、除、十六进制转十进制、十进制转十六进制、二进制转十进制等5个函数
源程序如下:
STACK1 SEGMENT PARA STACK          ;堆栈段定义
STACK_AREA DW 100H DUP(?)
STACK_BOTTOM EQU $-STACK_AREA
STACK1 ENDS
DATA1 SEGMENT                      ;数据段定义
FUNC DW 5 DUP(?)
HELP DB "1-MUL 2-DIV 3-HEX2DEC 4-DEC2HEX 5-BIN2DEC",0
MULTI_HEAD DB "MULTIPLY FUNCTION:",0
DIVI_HEAD DB "DIVIDE FUNCTION:",0
H2D_HEAD DB "HEX TO DEC FUNCTION:",0
D2H_HEAD DB "DEC TO HEX FUNCTION:",0
B2D_HEAD DB "BIN TO DEC FUNCTION:",0

SPACE DB ' '
DATA1 ENDS
CODE1 SEGMENT
MAIN PROC FAR
    ASSUME CS:CODE1,SS:STACK1,DS:DATA1
    MOV AX,STACK1          ; 初始化堆栈寄存器           
    MOV SS,AX
    MOV AX,STACK_BOTTOM
    MOV SP,AX
    MOV AX,DATA1
    MOV DS,AX
    MOV ES,AX                
    LEA SI,FUNC            ; 初始化函数表
    LEA AX,MULTI            
    MOV [SI],AX
    LEA AX,DIVI
    MOV [SI+2],AX
    LEA AX,HEX2DEC
    MOV [SI+4],AX
    LEA AX,DEC2HEX
    MOV [SI+6],AX
    LEA AX,BIN2DEC
    MOV [SI+8],AX
    
MAINLOOP:
    LEA AX,HELP             ; 使用键盘输入(0-5)控制循环,0代表推出
    CALL DISP 
    CALL GETNUM
    CMP AX,0
    JZ EXIT
    JB MAINLOOP
    CMP AX,5
    JA MAINLOOP
  
    SUB AX,1
    SHL AX,1
    
    PUSH SI
    ADD SI,AX
    CALL [SI]
    POP SI

    LEA AX,SPACE
    CALL DISP
    JMP MAINLOOP
EXIT:
    MOV AX,4C00H
    INT 21H
MAIN ENDP
MULTI PROC NEAR
    LEA AX,MULTI_HEAD
    CALL DISP           ; 显示头部文字
    CALL GETNUM         ; 获取第一个输入
    PUSH AX             ; 压栈        
    CALL GETNUM         ; 获取第二个输入
    POP BX              ; 将第一个输入取出
    XOR DX,DX           ; 将DX清0
    MUL BX              ; 执行乘法
    PUSH AX             ; 显示结果
    CALL DISPNUM
    RET 
MULTI  ENDP
DIVI PROC NEAR
    LEA AX,DIVI_HEAD    ; 显示头部文字
    CALL DISP         
    CALL GETNUM         ; 获取被除数
    PUSH AX             ; 压栈
    CALL GETNUM         ; 获取除数
    POP BX              ; 弹出被除数
    XCHG AX,BX          ; 交换AX,BX
    XOR DX,DX           ; 将DX清0
    DIV BX              ; 执行除法
    PUSH AX             ; 显示商
    CALL DISPNUM       
    PUSH DX
    LEA AX,SPACE        ; 打印空格
    CALL DISP           
    CALL DISPNUM        ; 显示余数
    RET
DIVI ENDP

HEX2DEC PROC NEAR
    LEA AX,H2D_HEAD    
    CALL DISP        
    CALL GETNUMHEX      ; 获取16进制输入       
    PUSH AX
    CALL DISPNUM        ; 使用10进制数出
    RET
HEX2DEC ENDP

DEC2HEX PROC NEAR
    LEA AX,D2H_HEAD
    CALL DISP
    CALL GETNUM         ; 获取10进制输入
    PUSH AX
    CALL DISPNUMHEX     ; 使用16进制输出
    RET 
DEC2HEX ENDP

BIN2DEC PROC NEAR
   LEA AX,B2D_HEAD   
   CALL DISP
   CALL GETNUMBIN      ; 获取2进制输入
   PUSH AX
   CALL DISPNUM        ; 10进制输出
   RET
BIN2DEC ENDP

GETNUM PROC NEAR
    PUSH DX             ; DX用于保存乘法高位
    PUSH BX             ; BX用于存中间结果
    PUSH CX             ; CX用于输入位数计数
    MOV BX,0
    MOV CX,5            ; 最多输入5位
    MOV DX,0
GETNUM_LP:
    MOV AH,1
    INT 21H 
    XOR AH,AH
    CMP AX,0DH          ; 0dH 为回车 判断为回车即跳出
    JZ GETNUM_EXIT
    SUB AX,'0'
    PUSH AX
    MOV AX,BX           ; 将中间结果x10 并累加
    MOV BX,10
    MUL BX
    MOV BX,AX
    POP AX
    ADD BX,AX
    LOOP GETNUM_LP
GETNUM_EXIT:
    MOV AX,BX
    POP CX
    POP BX
    POP DX
    RET 
GETNUM ENDP

GETNUMBIN PROC NEAR    ; 二进制输入与十进制类似,CX置为16其余不需赘述
    PUSH DX
    PUSH BX
    PUSH CX
    MOV BX,0
    MOV CX,16
    MOV DX,0
GETNUMBIN_LP:
    MOV AH,1
    INT 21H 
    XOR AH,AH
    CMP AX,0DH
    JZ GETNUMBIN_EXIT
    SUB AX,'0'
    PUSH AX
    MOV AX,BX
    MOV BX,2
    MUL BX
    MOV BX,AX
    POP AX
    ADD BX,AX
    LOOP GETNUMBIN_LP
GETNUMBIN_EXIT:
    MOV AX,BX
    POP CX
    POP BX
    POP DX
    RET 
GETNUMBIN ENDP

GETNUMHEX PROC NEAR  ; 十六进制输入需要判断输入数位是数字还是字母 并且区别对待
    PUSH DX          ; 为了简化,这里仅处理了对大写字母的判断
    PUSH BX
    PUSH CX
    MOV BX,0
    MOV CX,5
    MOV DX,0
GETNUMHEX_LP:
    MOV AH,1
    INT 21H 
    XOR AH,AH
    CMP AX,0DH
    JZ GETNUMHEX_EXIT
    CMP AX,'9'
    JA GETNUMHEX_HEX
    SUB AX,'0'
    JMP GETNUMHEX_LP_TAIL
GETNUMHEX_HEX:
    SUB AX,'A'
    ADD AX,10
GETNUMHEX_LP_TAIL:
    PUSH AX
    MOV AX,BX
    MOV BX,10H
    MUL BX
    MOV BX,AX
    POP AX
    ADD BX,AX
    LOOP GETNUMHEX_LP
GETNUMHEX_EXIT:
    MOV AX,BX
    POP CX
    POP BX
    POP DX
    RET 
GETNUMHEX ENDP
DISPNUM PROC NEAR       ; 数字显示,使用除法并倒序显示余数即可
    PUSH BP             
    MOV BP,SP
    PUSH BX            
    PUSH CX
    PUSH DX
    MOV AX,[BP+4]      ; AX存输入参数及中间结果
    MOV CX,0           ; CX存的是数字位数
    MOV BX,10          ; BX存的是进制数
DISPNUM_DIV:
    XOR DX,DX          ; 执行除法前先将DX清0
    DIV BX 
    PUSH DX
    INC CX
    CMP AX,0           ; 如果商为0,代表得到了最后一位数,可以退出
    JZ DISPNUM_DISPLAY
    JMP DISPNUM_DIV
DISPNUM_DISPLAY:       ; 取出余数并显示
    MOV AH,2
    POP DX
    ADD DX,'0'
    INT 21H
    LOOP DISPNUM_DISPLAY
DISPNUM_EXIT:
    POP DX
    POP CX
    POP BX
    POP BP
    RET 2              ; 由于使用了一个参数 所以RET 2
DISPNUM ENDP

DISPNUMHEX PROC NEAR   ; 十六进制输出类似,只需要判断是数字还是字母,区分对待即可
    PUSH BP
    MOV BP,SP
    PUSH BX
    PUSH CX
    PUSH DX
    MOV AX,[BP+4]
    MOV CX,0
    MOV BX,10H
DISPNUMHEX_DIV:
    XOR DX,DX
    DIV BX 
    PUSH DX
    INC CX
    CMP AX,0
    JZ DISPNUMHEX_DISPLAY
    JMP DISPNUMHEX_DIV
DISPNUMHEX_DISPLAY:
    MOV AH,2
    POP DX
    CMP DX,9                 ; 比较数位与9,大于则进入字母处理,小于等于进入数字处理
    JA DISPNUMHEX_HEX
    ADD DX,'0'
    JMP DISPNUMHEX_PRINT
DISPNUMHEX_HEX:
    ADD DX,'A'
    SUB DX,10
DISPNUMHEX_PRINT:
    INT 21H
    LOOP DISPNUMHEX_DISPLAY
DISPNUMHEX_EXIT:
    POP DX
    POP CX
    POP BX
    POP BP
    RET 2
DISPNUMHEX ENDP

DISP PROC       ; 字符串显示函数,用于显示以0结尾的字符串
   PUSH AX
   PUSH DX
   PUSH SI
   MOV SI,AX
   MOV AH,2
   XOR DX,DX
   CLD
DISP_LP:
   LODSB
   CMP AL,0     ; 判断是否结束
   JZ DISP_EXIT
   MOV DL,AL
   INT 21H
   JMP DISP_LP
DISP_EXIT:
   MOV DX,0AH   ; 输出回车符
   INT 21H
   MOV DX,0DH

   INT 21H
   POP SI
   POP DX
   POP AX
   RET 
DISP ENDP
CODE1 ENDS
END MAIN

[运行截图]

 二、
[要求] 使用函数表 完成字符串的大小写转换、增、删、查、替换、复制、比较
源程序如下:
STACK1 SEGMENT PARA STACK                                        ; 定义栈
STACK_AREA DW 100H DUP(?)
STACK_BOTTOM EQU $ - STACK_AREA
STACK1 ENDS
DATA1 SEGMENT 
STR1 DB "Tom and Marry dont go to school on Sunday",50 DUP(?),0  ; 
STR2 DB 'Sunday',0
STR3 DB 'TOM',0
STR4 DB 'Jerry',0
STR5 DB 'on',0
STR6 DB '520 day',0
BUFFER DB 0,100 DUP(?)
BUFFER2 DB 0,100 DUP(?)
FUNC DW 5 DUP(?)
DATA1 ENDS
CODE1 SEGMENT

MAIN PROC FAR
    ASSUME CS:CODE1,SS:STACK1,DS:DATA1
    MOV AX,STACK1
    MOV SS,AX
    MOV AX,STACK_BOTTOM
    MOV SP,AX
    MOV AX,DATA1
    MOV DS,AX
    MOV ES,AX
    LEA AX,STR1
    PUSH AX
    LEA AX,STR2
    PUSH AX
    LEA AX,STR6
    PUSH AX
    CALL REPLACE
    LEA AX,STR1
    CALL DISP

EXIT: 
    MOV AX,4C00H
    INT 21H
MAIN ENDP
;BIJIAO PAIXU TIHUAN

STRCAT PROC 
    PUSH BP
    MOV BP,SP
    PUSH AX
    PUSH SI
    PUSH DI
    MOV SI,[BP+4] ;mov dst string to SI 
    CLD
STRCAT_FINDEND:
    LODSB         
    CMP AL,0
    JZ STRCAT_CAT
    JMP STRCAT_FINDEND
STRCAT_CAT:
    MOV AX,[BP+6]
    PUSH AX
    DEC SI
    PUSH SI
    CALL STRCPY
    POP DI
    POP SI
    POP AX
    POP BP
    RET 2
STRCAT ENDP

STRCAT2 PROC
    PUSH SI
    MOV SI,DI
STRCAT2_FIND:
    LODSB 
    CMP AL,0
    JZ STRCAT2_EXIT
    JMP STRCAT2_FIND
STRCAT2_EXIT:
    RET
STRCAT2 ENDP 

STRCUT PROC
    PUSH BP
    MOV BP,SP
    PUSH SI
    PUSH DI
    PUSH CX
    MOV CX,[BP+4]  ;new length
    MOV SI,[BP+6]  ;source string
    REP LODSB 
    MOV [SI],CX    ;set 0
    POP CX
    POP DI
    POP SI
    POP BP
    RET 4
STRCUT ENDP

    
STRCPY PROC 
    PUSH BP
    MOV BP,SP
    PUSH AX
    PUSH SI
    PUSH DI
    MOV DI,[BP+4]
    MOV SI,[BP+6]
    CLD
STRCPY_LP:
    LODSB 
    STOSB
    CMP AL,0
    JZ STRCPY_END
    JMP STRCPY_LP
STRCPY_END:
    POP DI
    POP SI
    POP AX
    POP BP
    RET 4
STRCPY ENDP

STRCPY2 PROC
    PUSH AX
STRCPY2_LP:
    LODSB 
    CMP AL,0
    JZ STRCPY2_EXIT
    STOSB
    JMP STRCPY2_LP
STRCPY2_EXIT:
    POP AX
    RET 
STRCPY2 ENDP

STRCMP PROC
    PUSH BP
    MOV BP,SP
    PUSH SI
    PUSH DI
    MOV SI,[BP+6]
    MOV DI,[BP+4]
    MOV AX,0
STRCMP_LP:
    CLD
    CMPSB
    JZ STRCMP_EQ
    JG STRCMP_GT
    JL STRCMP_LS
STRCMP_EQ:
    CMP [SI-1],AL
    JNZ STRCMP_LP   ;两字符相同而不为0 则继续比较
    JMP STRCMP_EXIT ;为0 则结束 AX本身为0 不用再置于0
STRCMP_GT:
    MOV AX,1        ;大于则置1 小于置-1
    JMP STRCMP_EXIT
STRCMP_LS:
    MOV AX,-1
    JMP STRCMP_EXIT
STRCMP_EXIT:
    POP DI
    POP SI
    POP BP
    RET 4
STRCMP ENDP

UPPERCASE PROC
    PUSH BP
    MOV BP,SP
    PUSH SI
    PUSH AX
    MOV SI,[BP+4]
UPPERCASE_LP:
    LODSB
    CMP AL,0
    JZ UPPERCASE_EXIT
    CMP AL,'a'
    JAE UPPERCASE_a
    JMP UPPERCASE_LP
UPPERCASE_a:
    CMP AL,'z'
    JBE UPPERCASE_z
    JMP UPPERCASE_LP
UPPERCASE_z:
    XOR AL,20H
    MOV [SI-1],AL
    JMP UPPERCASE_LP
UPPERCASE_EXIT:
    POP AX
    POP SI
    POP BP
    RET 4
UPPERCASE ENDP

REPLACE PROC
    PUSH BP
    MOV BP,SP
    PUSH SI
    PUSH DI
    PUSH AX
    PUSH BX
    PUSH CX
    MOV SI,[BP+8]   ;src : string to be operated    
    LEA BX,BUFFER   ;store buffer address
    CLD
REPLACE_LP:
    MOV DI,[BP+6]   ;rep : string to be replaced
    PUSH SI
    PUSH DI
    CALL FIND
    CMP AX,-1               
    JNZ REPLACE_FOUND
    JZ  REPLACE_NOT_FOUND
REPLACE_FOUND:
    MOV CX,AX     ;copy src to buffer
    SUB CX,SI 
    MOV DI,BX
    REP MOVSB
    
    PUSH SI       ;copy dst to buffer
    MOV SI,[BP+4] 
    CALL STRCPY2
    POP SI
    MOV BX,DI
    
    MOV CX,-1
    MOV DI,[BP+6] ;calculate length of rep 
    MOV AL,0
    REPNE SCASB

    NEG CX
    SUB CX,2      ;CX=1+len(rep)+1     
    ADD SI,CX

    JMP REPLACE_LP

REPLACE_NOT_FOUND:
    MOV DI,BX           ;copy left src to buff
    CALL STRCPY2   
    
    LEA SI,BUFFER       ;copy buffer to src
    MOV DI,[BP+8]
    CALL STRCPY2        

    POP CX
    POP BX
    POP AX
    POP DI
    POP SI
    POP BP
    RET 6

REPLACE ENDP
   
FIND PROC
    PUSH BP
    MOV BP,SP
    PUSH SI
    PUSH DI
    PUSH CX
    MOV SI,[BP+6]   ;string to find in
    MOV DI,[BP+4]   ;string to match
    MOV AX,0
    MOV CX,0
    CLD
FIND_LP:
    CMP [DI],AL
    JZ FIND_SUCCESS
    CMP [SI],AL
    JZ FIND_FAILED
    CMPSB 
    JZ FIND_MATCH
    JNZ FIND_NOTMATCH
FIND_MATCH:
    INC CX
    JMP FIND_LP
FIND_NOTMATCH:
    MOV CX,0
    MOV DI,[BP+4]    
    JMP FIND_LP
FIND_SUCCESS:
    SUB SI,CX
    MOV AX,SI
    JMP FIND_EXIT
FIND_FAILED:
    MOV AX,-1
    JMP FIND_EXIT
FIND_EXIT:
    POP CX
    POP DI
    POP SI
    POP BP
    RET 4
FIND ENDP

GETSTR PROC  
    PUSH AX
    PUSH SI
    MOV DI,AX
    MOV AH,1
    CLD

GETSTR_LP:

    INT 21H
    CMP AL,0DH
    JZ GETSTR_EXIT
    STOSB
    JMP GETSTR_LP
GETSTR_EXIT:
    MOV AL,0
    STOSB
    POP SI
    POP AX
    RET 
GETSTR ENDP

DISP PROC             ;
   PUSH AX
   PUSH DX
   PUSH SI
   MOV SI,AX
   MOV AH,2
   XOR DX,DX
   CLD
DISP_LP:
   LODSB
   CMP AL,0
   JZ DISP_EXIT
   MOV DL,AL
   INT 21H
   JMP DISP_LP
DISP_EXIT:
   MOV DX,0AH   ;NEW LINE
   INT 21H
   MOV DX,0DH

   INT 21H
   POP SI
   POP DX
   POP AX
   RET 
DISP ENDP

CODE1 ENDS
END MAIN

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值