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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值