x86函数表

进制转化、乘除运算以及字符串处理的函数表

Posted by Echo on May 14, 2018

实现函数表对于我们理解函数调用的实质以及函数调用时堆栈的应用有很大的帮助。

进制转化、乘除运算的函数表实现

功能简介:

程序实现函数表功能有十六进制转十进制,十进制转十六进制,
乘法,除法,二进制转十进制,并以交互式选项的方式一一呈现。

这里展示一下程序运行的截图:

x86-functab

代码演示:

;stack segment define
STACK1		SEGMENT	PARA STACK
STACK_AREA	DW		100H DUP(?)
STACK_BTM	EQU		$ - STACK_AREA
STACK1		ENDS

DATA1		SEGMENT
RES_BCD		DB		10 DUP(0)	;存储乘法结果的BCD码
OPR1		DW		0	;操作数1
RES			DW		2 DUP(0)	;结果
BUF			DB		6	;最大6个字符,65536\n
			DB 		?	;实际输入字符个数
			DB		6 DUP(?)	;存放字符

			; 定义函数指针数组
FUNC 		DW 		5 DUP(?)
TABLEN		DB		0
MIAN_ERR	DB		'Index out of range!', '$'
MAIN_MSG	DB		'Please input your choice(0.exit;1.DEC2HEX;2.HEX2DEC;3.MULTPLY;4.DIVIDE): ', '$'
IN_DEC_MSG	DB		'Please input a number in DEC: ','$'
OUT_HEX_MSG	DB		'The number in HEX is: ','$'
IN_HEX_MSG	DB		'Please input a number in HEX: ','$'
OUT_DEC_MSG	DB		'The number in DEC is: ','$'
DIV_0_MSG	DB		'Divided by ZERO!', '$'
DATA1		ENDS


CODE1		SEGMENT
			ASSUME	CS:CODE1, DS:DATA1, SS:STACK1, ES:DATA1

;The first choice DEC2HEX
DECTOHEX	PROC
			LEA		DX, IN_DEC_MSG
			CALL	HINTS
			CALL	NEWLINE
			CALL	READ_DEC	;读一个数到AX中
			MOV		BX, AX
			CALL	NEWLINE
			LEA		DX, OUT_HEX_MSG
			CALL	HINTS
			CALL	DISP_16		;将BX中的数以16进制显示
			RET
DECTOHEX	ENDP

;The sceond choice HEXTODEC
HEXTODEC	PROC
			LEA		DX, IN_HEX_MSG
			CALL	HINTS
			CALL	NEWLINE
			CALL	READ_HEX	;读一个数到AX中
			CALL	NEWLINE
			LEA		DX, OUT_DEC_MSG
			CALL	HINTS
			CALL	DISP_10
			RET
HEXTODEC	ENDP
			
;The third choice MULTPLY
MULTPLY		PROC
			CALL 	READ_DEC
			MOV 	OPR1, AX
			CALL	NEWLINE
			MOV		DL, 'x'
			MOV		AH, 2
			INT		21H
			CALl	NEWLINE
			CALL 	READ_DEC
			MUL 	OPR1
			CALL	NEWLINE
			MOV 	WORD PTR RES, AX
			MOV 	WORD PTR RES+2, DX
			CALL	DISP_BCDEC
			RET
MULTPLY		ENDP

;The fourth choice DIVIDE
DIVIDE		PROC
			CALL 	READ_DEC
			MOV 	OPR1, AX
			CALL	NEWLINE
			MOV		DL, '/'
			MOV		AH, 2
			INT		21H
			CALl	NEWLINE
			CALL	READ_DEC
			CMP		AX, 0
			JZ		DIV_0_ERR
			
			CALL	NEWLINE
			MOV		BX, AX
			MOV		AX, OPR1
			XOR		DX, DX
			DIV		BX
			CALL	DISP_10
			JMP		RET_DIV

DIV_0_ERR:	CALL	NEWLINE
			LEA		DX, DIV_0_MSG
			CALL	HINTS
			;CALL	NEWLINE
			
RET_DIV:	RET
DIVIDE		ENDP

;十进制显示32bit数
DISP_BCDEC	PROC	NEAR
			PUSH	DS
			PUSH	SI
			mov     ax, DATA1
			mov     ds, ax
			mov     cx, 32          ;要进行十六次移位,利用adc获得

			XOR		AX, AX
			XOR		BX, BX
			XOR		DX, DX
loop_wai: 	shl     RES, 1          ;得到 var 的 Bi 位
			RCL		RES+2, 1
			; LEA		BX, RES_BCD
			; ADD		BX, 9
			mov     bx, 9
			push    cx
			mov     cx, 10

loop_nei:	mov     al, [bx]        ;执行 buf*2 + Bi 操作
			adc     al, al
			aaa                     ;非压缩格式 BCD 码调整
			mov     [bx], al
			dec     bx
			loop    loop_nei        ;内循环为 9 次
			pop     cx
			loop    loop_wai        ;外循环为 32 次
			
			MOV		CX, 10
			MOV 	SI, OFFSET RES_BCD
PREFIX_0:	MOV 	DL, [SI]
			CMP		DL, 0H
			JNZ		DISP_DEC
			INC 	SI
			DEC		CX
			JZ		DISP_ZERO
			JMP 	PREFIX_0
DISP_DEC:	MOV 	DL, [SI]
			ADD 	DL, 30H
			MOV 	AH, 2
			INT 	21H
			INC 	SI
			LOOP 	DISP_DEC
			JMP 	DISP_D
			
DISP_ZERO:	MOV 	AH, 2
			MOV 	DL, 30H
			INT 	21H
			
DISP_D:		MOV 	AH, 2
			MOV 	DL, 44H
			INT 	21H
			
			POP		SI
			POP		DS
			RET
DISP_BCDEC	ENDP

			
;读一个16位十进制数到AX
READ_DEC	PROC 	NEAR
			PUSH	DS
			PUSH	SI
			MOV 	AX, DATA1	;缓冲区基地址
			MOV 	DS, AX
			LEA		DX, BUF		;缓冲区首地址偏移
			MOV 	AH, 0AH
			INT 	21H
			
			MOV 	AX, 0
			MOV 	CX, 10		;作为固定数10
			MOV 	SI, DX
			ADD 	SI, 2
LP_R_D:		MOV		BL, [SI]
			CMP 	BL, 0DH
			JE		BRK
			MUL 	CX
			AND		BX, 00FFH
			SUB 	BX, 30H
			ADD 	AX, BX
			INC		SI
			JMP 	LP_R_D
			
BRK:		POP		SI
			POP		DS
			RET
READ_DEC	ENDP	

;读一个16位十六进制数到AX
READ_HEX	PROC 	NEAR
			PUSH	DS
			PUSH	SI
			MOV 	AX, DATA1	;缓冲区基地址
			MOV 	DS, AX
			LEA		DX, BUF		;缓冲区首地址偏移
			MOV 	AH, 0AH
			INT 	21H
			
			XOR 	AX, AX
			MOV 	CX, 16		;作为固定数10
			MOV 	SI, DX
			ADD 	SI, 2
LP_R_H:		MOV		BL, [SI]
			CMP 	BL, 0DH
			JE		BRK_H
			MUL 	CX
			AND		BX, 00FFH
			SUB 	BX, 30H
			ADD 	AX, BX
			INC		SI
			JMP 	LP_R_H
			
BRK_H:		POP		SI
			POP		DS
			RET
READ_HEX	ENDP	
		
;将AX中的数以10进制显示
DISP_10		PROC 	NEAR
			MOV 	CX, 0
LP_10_real:	MOV 	DX, 0
			MOV		BX, 10
			DIV 	BX			;商在AX,余数在DX
			PUSH 	DX			;余数入栈
			INC 	CX
			CMP 	AX, 0
			JNZ 	LP_10_real		
LP_10_num:	POP 	AX
			AND		AL, 0FH
			ADD 	AL, 30H
			MOV		AH, 2
			MOV 	DL, AL
			INT 	21H
			LOOP 	LP_10_num
			MOV		AH, 2		;打印10进制末尾D
			MOV 	DL, 44H
			INT 	21H
			
			RET
DISP_10		ENDP
		
;将BX中的数以16进制显示
DISP_16		PROC 	NEAR
			MOV 	CH, 4
LP_16_real:	MOV 	CL, 4	
			ROL 	BX, CL		;循环左移四位将高四位存到低四位
			MOV 	AL, BL		;
			AND		AL, 0FH		;取低四位
			ADD 	AL, 30H
			CMP 	AL, 3AH
			JB		LP_16_num
			ADD 	AL, 7H
LP_16_num:	MOV		AH, 2
			MOV 	DL, AL
			INT 	21H
			DEC 	CH
			JNZ 	LP_16_real
			
			MOV		AH, 2
			MOV		DL, 48H
			INT		21H
			RET
DISP_16		ENDP					


HINTS		PROC
			PUSH	AX
			MOV		AH, 9
			INT 	21H
			POP		AX
			RET
HINTS		ENDP

NEWLINE		PROC
			PUSH	AX
			PUSH	DX
			MOV		AH, 2		;打印回车
			MOV 	DL, 0AH
			INT 	21H
			POP		DX
			POP		AX
			RET
NEWLINE		ENDP

MAIN		PROC	FAR
			MOV		AX, STACK1
			MOV		SS, AX
			MOV		SP, STACK_BTM
			MOV		AX, DATA1
			MOV 	DS, AX
			MOV 	ES, AX
			; 初始化函数指针数组
			MOV 	SI, OFFSET FUNC
			MOV 	BX, OFFSET DECTOHEX
			MOV 	[SI], BX
			INC		TABLEN
			MOV 	BX, OFFSET HEXTODEC
			MOV 	[SI+2], BX
			INC		TABLEN
			MOV 	BX, OFFSET MULTPLY
			MOV 	[SI+4], BX
			INC		TABLEN
			MOV 	BX, OFFSET DIVIDE
			MOV 	[SI+6], BX
			INC		TABLEN
			;MOV 	BX, OFFSET BINTODEC
			; MOV 	[SI+8], BX
			; 根据输入数值求出目标函数在函数指针数组中的偏移量并进行跳转
			;PUSH	SI
			
MLOOP:		LEA		DX, MAIN_MSG
			CALL	HINTS
			MOV		AH, 1
			INT		21H
			CALL	NEWLINE
			SUB		AL, 30H
			CMP 	AL, 0
			JZ 		EXIT
			CMP		AL, TABLEN
			JBE		REAL_MLP
			LEA		DX, MIAN_ERR
			CALL	HINTS
			CALL	NEWLINE
			JMP		MLOOP
REAL_MLP:	DEC 	AL
			SHL 	AL, 1
			MOV 	BL, AL
			AND		BX, 00FFH
			; POP		SI
			; PUSH	SI
			CALL 	[SI+BX]
			CALL	NEWLINE
			JMP 	MLOOP			
			
EXIT:		MOV		AX, 4C00H
			INT		21H
MAIN		ENDP
CODE1		ENDS
			END		MAIN

字符串处理的函数表实现

功能简介:

程序实现字符串的大小写转化、增加、查找、复制、删除、
替换、比较以及字典排序,并将这些操作以交互式集成为3个函数。

这里展示一下程序运行的截图:

x86-funcstr

代码演示:

;stack segment define
STACK1		SEGMENT	PARA STACK
STACK_AREA	DW		100H DUP(?)
STACK_BTM	EQU		$ - STACK_AREA
STACK1		ENDS

DATA0		SEGMENT
			; 定义函数指针数组
FUNC 		DW 		5 DUP(?)
TABLEN		DB		0
MIAN_ERR	DB		'Index out of range!', '$'
MAIN_MSG	DB		'Please input your choice(0.exit;1.STRCPY;2.STRREP;3.DIC_SORT): ', '$'
IN_DEC_MSG	DB		'Please input a number in DEC: ','$'
OUT_HEX_MSG	DB		'The number in HEX is: ','$'
IN_HEX_MSG	DB		'Please input a number in HEX: ','$'
OUT_DEC_MSG	DB		'The number in DEC is: ','$'
DIV_0_MSG	DB		'Divided by ZERO!', '$'
DATA0		ENDS

;data segment define
DATA1		SEGMENT
BUF			DB		10H DUP(0)
SRC_CPY		DB 		'Hello, x86!'
			DB 		'$'
LEN_CPY		EQU 	$ - SRC_CPY
DST			DB 		LEN_CPY DUP(0)
DATA1		ENDS

;data segment define
DATA2		SEGMENT
FLAG		DW		0		;默认前移
DIFF		DW		0		;子串和替换串长度一致
RPSTR_BUF	DB 		20H
RPLEN_REP		DB		?
RPSTR		DB 		1EH	DUP(?)
SBSTR_BUF	DB 		20H
SBLEN_REP		DB		?
SBSTR		DB 		1EH	DUP(?)
SRC_REP_BUF	DB 		0FFH
LEN_REP			DB		?
SRC_REP		DB 		0FEH DUP(?)
BUFF_		DB		010H DUP(?)
DATA2		ENDS

;data segment define
DATA3		SEGMENT
IN_MSG		DB	'Please input strings separated by SPACE and ended by ENTER:(only letters)','$'
OUT_MSG		DB	'The dictionary sort result is:', '$'
TMP_BUF		DB	10H DUP(0)
TMP_LEN		DW	0
STR_ARR		DB	0FFH
			DB	?
STRS		DB	0FCH DUP(0)
ARR_LEN		DW	0
CMP_FLAG	DW	0		;0-不需要排序,1-需要排序
;INDEX_ARR	DW	0FFH DUP(0)
DATA3		ENDS

CODE1		SEGMENT
			ASSUME	CS:CODE1, DS:DATA0, SS:STACK1, ES:DATA0		

;-------------------1----------------------			
;The first choice of functab
STRCPY_IN	PROC
			PUSH	DS
			PUSH	ES
			PUSH	SI
			MOV		AX, DATA1
			MOV		DS, AX
			
			MOV 	SI, OFFSET SRC_CPY
			MOV	 	DI, OFFSET SRC_CPY	
			ADD		DI, LEN_CPY
			SUB		DI, 3
			MOV		CX, LEN_CPY
			CALL	STRCPY
			
			LEA		DX, SRC_CPY
			CALL	HINTS
			
			POP		SI
			POP		ES
			POP		DS
			RET
STRCPY_IN	ENDP

;源地址SI,目的地址DI,拷贝长度CX
STRCPY		PROC
			PUSH	ES				;维护ES
			PUSH	DS
			POP 	ES				;ES与DS处于同一个段
			MOV		BX, SI			;暂存SI
			
			CMP 	SI, DI
			JZ 		BRK
			
			JAE		FORDER			;SI >= DI -> forward
			ADD 	SI, CX
			DEC 	SI
			CMP 	SI, DI			;SI+LEN_CPY<=DI -> forward
			JBE		FORDER
BACKER:		STD
			ADD 	DI, CX
			DEC 	DI
			JMP 	CPY
			
FORDER:		CLD	
			MOV 	SI, BX
			JMP 	CPY
			
CPY:		LODSB	
			STOSB
			LOOP	CPY
			
BRK:		POP 	ES
			RET
STRCPY 		ENDP	
;-------------------1----------------------			

;------------------2--------------------
;The second choice of functab
STRREP_IN	PROC
			PUSH	DS
			PUSH	ES
			PUSH	SI
			MOV 	AX, DATA2
			MOV 	DS, AX
			MOV		ES, AX
	
			LEA		DX, SRC_REP_BUF		;SRC_REP缓冲区首地址偏移
			CALL	READ_STR
			CALL 	NEWLINE
			LEA 	DX, SBSTR_BUF	;SBSTR子串缓冲区首地址偏移
			CALL 	READ_STR
			CALL 	DISP_SP
			LEA		DX, RPSTR_BUF
			CALL 	READ_STR
			CALL	NEWLINE
			
			MOV 	CL, SBLEN_REP		;子串长度
			AND 	CX, 00FFH
			MOV 	BL, RPLEN_REP		;替换串长度
			AND 	BX, 00FFH		
			CMP 	BX, CX
			JBE		FW
			MOV 	FLAG, 1			;1代表后移
			SUB		BX, CX
			MOV 	DIFF, BX
			JMP		RP

FW:			SUB		CX, BX
			MOV 	DIFF, CX
			
RP:			CALL 	REP_STR
			POP		SI
			POP		ES
			POP		DS
			RET
STRREP_IN	ENDP

;将地址缓冲区首地址偏移存入DX
READ_STR	PROC
			PUSH	AX
			MOV 	AH, 0AH
			INT 	21H
			POP		AX
			RET
READ_STR	ENDP

REP_STR		PROC
			PUSH 	ES
			PUSH	DS
			POP 	ES
			
			MOV 	SI, OFFSET SRC_REP 
			MOV 	CL, LEN_REP
			AND		CX, 00FFH
LP_SRC_REP:		PUSH 	CX
			PUSH	SI
			MOV		CL, SBLEN_REP			;获取子串长度
			AND 	CX, 00FFH
			MOV 	DI, OFFSET SBSTR
			CLD
LP_CMP:		CMPSB
			JNZ		CONTINUE			
			LOOP	LP_CMP			;DS:[SI]==ES:[DI]->LP
			POP 	BX				;匹配串初始位置
			POP 	CX				;决定替换之后原串长度更新
			SUB		CL, SBLEN_REP		;预置CX
			SBB		CH, 0
			INC		CX
			PUSH	CX
			PUSH 	BX
			CMP		FLAG, 0
			JZ		MVFW				;剩余的串前移
MVBK:		ADD 	SI, CX
			DEC		SI
			MOV 	DI, SI
			ADD 	DI, DIFF
			STD
			REP		MOVSB
			JMP		REPLACE
MVFW:		MOV 	DI, SI
			SUB 	DI, DIFF
			CLD
			REP 	MOVSB
REPLACE:	POP		DI
			MOV		CL, RPLEN_REP			;替换穿作为SI,原串作为DI
			AND 	CX, 00FFH
			MOV		SI, OFFSET RPSTR
			CLD
			REP		MOVSB
			POP 	CX
			MOV 	SI, DI
			;LOOP 	LP_SRC_REP
			JMP		REAL_CNT

CONTINUE:	POP		SI
			INC		SI
			POP 	CX
REAL_CNT:	LOOP 	LP_SRC_REP
;显示处理结果	
DEL_END:	MOV		BYTE PTR [SI], 24H
			MOV		AH, 9
			MOV		DX, OFFSET SRC_REP
			INT		21H
			
			POP 	ES
			RET
REP_STR		ENDP


DISP_SP		PROC
			PUSH	AX
			PUSH	DX
			MOV		AH, 2		;打印空格
			MOV 	DL, 0AH
			INT 	21H
			MOV		AH, 2		;打印箭头
			MOV 	DL, 2DH
			INT 	21H
			MOV		AH, 2		;
			MOV 	DL, 3EH
			INT 	21H
			MOV		AH, 2		;打印空格
			MOV 	DL, 20H
			INT 	21H
			POP		DX
			POP		AX
			RET
DISP_SP		ENDP
;------------------2--------------------

;-----------------3---------------------
;将地址缓冲区首地址偏移存入DX
DICSORT_IN	PROC
			PUSH	ES
			PUSH	DS
			PUSH	SI
			MOV		AX, DATA3
			MOV		DS, AX
			MOV		ES, AX
			;input hints
			LEA		DX, IN_MSG
			CALL	HINTS
			CALL	NEWLINE

			LEA		DX, STR_ARR
			CALL	READ_CAPSTR		;读字符串并统一为大写
			CALL	DICSORT
			MOV		AH, 2		;打印回车
			MOV 	DL, 0AH
			INT 	21H
			;ouput hints
			LEA		DX, OUT_MSG
			CALL	HINTS
			CALL	NEWLINE
			;output disp
			LEA		DX, STRS
			CALL	HINTS

			POP		SI
			POP		DS
			POP		ES
			RET
DICSORT_IN	ENDP

DICSORT		PROC
			
			
LP1_DIC:	MOV		AX, 1			;标志位
			LEA		SI, STRS		;首个字符串起始index
			MOV		CX, ARR_LEN		;字符串的个数
			DEC		CX				;冒泡排序,比较n-1次
			MOV		DI, SI			;取两个index,DI为前字符串,SI为后字符串
LP2_DIC:	;MOV		SI, [BX+2]
			CALL	GET_NEXT		;从SI指向的字符串开始,将下一个字符串的指针存在SI中
			CALL	DIC_CMP			;比较并按两个输入字符串,指针为DI,SI[不能改变DI,SI],结果存入CMP_FLAG
			CMP 	CMP_FLAG, 0
			JZ		CONTINUE_DIC
			CALL 	CHG_STR			;交换SI,DI的两个字符串
			XOR 	AX, AX			;设立FLAG表示已交换
CONTINUE_DIC:
			MOV 	DI, SI
			LOOP	LP2_DIC
			CMP 	AX, 1
			JZ		EXIT_DIC		
			JMP		LP1_DIC

EXIT_DIC:	RET
DICSORT		ENDP


READ_CAPSTR	PROC
			PUSH	ES
			PUSH	DS
			POP		ES
			
			MOV 	AH, 0AH
			INT 	21H
			
			;LEA		BX, INDEX_ARR
			MOV		SI, DX
			INC		SI			;加1获得len
			MOV		CL, [SI]
			AND		CX, 00FFH
			INC		SI			;位移到字符串起始地址
			; MOV		[BX], SI
			; ADD		BX, 2
			MOV		DI, SI
			CLD
LP1_RD:		LODSB
			CMP		AL, 'a'
			JB		CONTINUE_RD
			CMP		AL, 'z'
			JA		CONTINUE_RD
			SUB		AL, 20H
CONTINUE_RD:CMP		AL, 20H
			JNZ		CONTINUE_R
			INC		ARR_LEN
			;MOV		[BX], SI
			;ADD		BX, 2
CONTINUE_R:	STOSB		
			LOOP	LP1_RD
			MOV		BYTE PTR [DI], 20H
;			MOV		BYTE PTR [DI+1], 0DH
			MOV		BYTE PTR [DI+1], '$'
			INC		ARR_LEN
			
			POP		ES
			RET
READ_CAPSTR	ENDP

CHG_STR		PROC
			PUSH	ES
			PUSH	AX
			PUSH	CX
			PUSH	DI
			PUSH	SI	

			PUSH	DS
			POP		ES
			;前字符串拷贝到TMP中
			MOV		CX, SI
			SUB		CX, DI		;获得前字符串的长度
			MOV		TMP_LEN, CX
			MOV		SI, DI		;设定源地址
			LEA		DI, TMP_BUF
			CALL	STRCPY
			;后字符串拷贝到前字符串中
			POP		SI		;将后字符串取出作为源地址
			MOV		AX, SI	;将SI暂存到AX中
			POP		DI		;前字符串取出作为目的地址
			PUSH	DI		;入栈保存
			;PUSH	SI
			CALL	GET_NEXT	;获得后字符串长度
			MOV		CX, SI
			SUB		CX, AX
			MOV		SI, AX		;将AX返还给SI
			CALL	STRCPY		;由于是++拷贝,故拷贝完之后的DI作为下一次拷贝的目的地址
			PUSH	DI			;DI是下一个字符串新的起始地址,即CONTINUE_DIC中应该更新的SI
			;将前字符串拷贝到后字符串中
			LEA		SI, TMP_BUF
			MOV		CX, TMP_LEN
			CALL	STRCPY

			POP		SI
			POP		DI
			POP		CX
			POP		AX
			POP		ES
			RET
CHG_STR		ENDP

GET_NEXT	PROC
			PUSH	ES
			PUSH	AX
			PUSH	DS
			POP		ES

			CLD
LP_NEXT:	LODSB
			CMP		AL, 20H		;若是单个字符串结尾,则+1记录为下一个字符串开始index
			JNZ		LP_NEXT

			POP 	AX
			POP		ES
			RET
GET_NEXT	ENDP

;比较并按两个输入字符串,指针为DI,SI
DIC_CMP		PROC
			PUSH	ES
			PUSH	AX
			;PUSH	BX
			PUSH	CX
			PUSH	SI
			PUSH 	DI

			PUSH	DS
			POP		ES
			
			MOV 	CX, SI
			SUB		CX, DI		;将前一个字符串的长度作为比较长度
			CLD
			MOV		CMP_FLAG, 0	;清空排序标志位(两个内存数不能操作)
LP_CMP_DIC:	CMPSB
			JZ 		CONTINUE_CMP
			;JA		CMP1	
			JA		EXIT_CMP		;DI在前,SI在后,故采用JA	
			MOV		CMP_FLAG, 1
			JMP 	EXIT_CMP
CONTINUE_CMP:
			LOOP	LP_CMP_DIC	

EXIT_CMP:	POP		DI
			POP		SI
			POP		CX
			;POP		BX
			POP		AX
			POP		ES
			RET
DIC_CMP		ENDP
;-----------------3---------------------

HINTS		PROC
			PUSH	AX
			MOV		AH, 9
			INT 	21H
			POP		AX
			RET
HINTS		ENDP

NEWLINE		PROC
			PUSH	AX
			PUSH	DX
			MOV		AH, 2		;打印回车
			MOV 	DL, 0AH
			INT 	21H
			POP		DX
			POP		AX
			RET
NEWLINE		ENDP
	
MAIN		PROC	FAR
			MOV		AX, STACK1
			MOV		SS, AX
			MOV		SP, STACK_BTM
			MOV		AX, DATA0
			MOV 	DS, AX
			MOV 	ES, AX
			; 初始化函数指针数组
			MOV 	SI, OFFSET FUNC
			MOV 	BX, OFFSET STRCPY_IN
			MOV 	[SI], BX
			INC		TABLEN
			MOV 	BX, OFFSET STRREP_IN
			MOV 	[SI+2], BX
			INC		TABLEN
			MOV 	BX, OFFSET DICSORT_IN
			MOV 	[SI+4], BX
			INC		TABLEN
			; MOV 	BX, OFFSET DIVIDE
			; MOV 	[SI+6], BX
			; INC		TABLEN
			;MOV 	BX, OFFSET BINTODEC
			; MOV 	[SI+8], BX
			; 根据输入数值求出目标函数在函数指针数组中的偏移量并进行跳转
			; PUSH	SI
			
MLOOP:		LEA		DX, MAIN_MSG
			CALL	HINTS
			MOV		AH, 1
			INT		21H
			CALL	NEWLINE
			SUB		AL, 30H
			CMP 	AL, 0
			JZ 		EXIT
			CMP		AL, TABLEN
			JBE		REAL_MLP
			LEA		DX, MIAN_ERR
			CALL	HINTS
			CALL	NEWLINE
			JMP		MLOOP
REAL_MLP:	DEC 	AL
			SHL 	AL, 1
			MOV 	BL, AL
			AND		BX, 00FFH
			; POP		SI
			; PUSH	SI
			CALL 	[SI+BX]
			CALL	NEWLINE
			JMP 	MLOOP			
			
EXIT:		MOV		AX, 4C00H
			INT		21H
MAIN		ENDP
CODE1		ENDS
			END		MAIN

以上便是关于函数表实现的x86程序演示,引用请注明出处(https://echo-ji.github.io/2018/05/14/x86-函数表/)。