⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ex8.asm

📁 ART OF Assembly Language Programming, 很不错
💻 ASM
📖 第 1 页 / 共 2 页
字号:
; Sample program for Chapter Eight
; Demonstrates the use of many MASM features discussed in Chapter Six
; including label types, constants, segment ordering, procedures, equates,
; address expressions, coercion and type operators, segment prefixes,
; the assume directive, conditional assembly, macros, listing directives,
; separate assembly, and using the UCR Standard Library.
;
; Include the header files for the UCR Standard Library.  Note that the
; "stdlib.a" file defines two segments; MASM will load these segments into
; memory before "dseg" in this program.
;
; The ".nolist" directive tells MASM not to list out all the macros for
; the standard library when producing an assembly listing.  Doing so would
; increase the size of the listing by many tens of pages and would tend to
; obscure the real code in this program.
;
; The ".list" directive turns the listing back on after MASM gets past the
; standard library files.  Note that these two directives (".nolist" and
; ".list") are only active if you produce an assembly listing using MASM's
; "/Fl" command line parameter.


		.nolist
		include 	stdlib.a
		includelib	stdlib.lib
		.list



; The following statement includes the special header file for this
; particular program.  The header file contains external definitions
; and various data type definitions.

		include		matrix.a


; The following two statements allow us to use 80386 instructions
; in the program.  The ".386" directive turns on the 80386 instruction
; set, the "option" directive tells MASM to use 16-bit segments by
; default (when using 80386 instructions, 32-bit segments are the default).
; DOS real mode programs must be written using 16-bit segments.

		.386
		option	segment:use16



dseg		segment	para public 'data'

Rows		integer	?		;Number of rows in matrices
Columns		integer	?		;Number of columns in matrices


; Input line is an input buffer this code uses to read a string of text
; from the user.  In particular, the GetWholeNumber procedure passes the
; address of InputLine to the GETS routine that reads a line of text
; from the user and places each character into this array.  GETS reads
; a maximum of 127 characters plus the enter key from the user.  It zero
; terminates that string (replacing the ASCII code for the ENTER key with
; a zero).  Therefore, this array needs to be at least 128 bytes long to
; prevent the possibility of buffer overflow.
;
; Note that the GetArray module also uses this array.

InputLine	char	128 dup (0)


; The following two pointers point at arrays of integers.
; This program dynamically allocates storage for the actual array data
; once the user tells the program how big the arrays should be.  The
; Rows and Columns variables above determine the respective sizes of
; these arrays.  After allocating the storage with a call to MALLOC,
; this program stores the pointers to these arrays into the following
; two pointer variables.

RowArray	dword	?		;Pointer to Row values
ColArray	dword	?		;Pointer to column values.



; ResultArrays is an array of dope vectors(*) to hold the results
; from the matrix operations:
;
; [0]- addition table
; [1]- subtraction table
; [2]- multiplication table
; [3]- division table
;
; [4]- modulo (remainder) table -- if the symbol "DoMOD" is defined.
;
; The equate that follows the ResultArrays declaration computes the number
; of elements in the array.  "$" is the offset into dseg immediately after
; the last byte of ResultArrays.  Subtracting this value from ResultArrays
; computes the number of bytes in ResultArrays.  Dividing this by the size
; of a single dope vector produces the number of elements in the array.
; This is an excellent example of how you can use address expressions in
; an assembly language program.
;
; The IFDEF DoMOD code demonstrates how easy it is to extend this matrix.
; Defining the symbol "DoMOD" adds another entry to this array.  The
; rest of the program adjusts for this new entry automatically.
;
; You can easily add new items to this array of dope vectors.  You will
; need to supply a title and a function to compute the matrice's entries.
; Other than that, however, this program automatically adjusts to any new
; entries you add to the dope vector array.
;
; (*) A "Dope Vector" is a data structure that describes a dynamically
; allocated array.  A typical dope vector contains the maximum value for
; each dimension, a pointer to the array data in memory, and some other
; possible information.  This program also stores a pointer to an array
; title and a pointer to an arithmetic function in the dope vector.


ResultArrays	DopeVec	{AddTbl,Addition}, {SubTbl,Subtraction}
		DopeVec	{MulTbl,Multiplication}, {DivTbl,Division}

		ifdef	DoMOD
		DopeVec	{ModTbl,Modulo}
		endif

; Add any new functions of your own at this point, before the following equate:


RASize		=	($-ResultArrays) / (sizeof DopeVec)


; Titles for each of the four (five) matrices.

AddTbl		char	"Addition Table",0
SubTbl  	char	"Subtraction Table",0
MulTbl		char	"Multiplication Table",0
DivTbl		char	"Division Table",0

		ifdef	DoMOD
ModTbl		char	"Modulo (Remainder) Table",0
		endif

; This would be a good place to put a title for any new array you create.

dseg		ends




; Putting PrintMat inside its own segment demonstrates that you can have
; multiple code segments within a program.  There is no reason we couldn't
; have put "PrintMat" in CSEG other than to demonstrate a far call to a
; different segment.

PrintSeg	segment	para public 'PrintSeg'

; PrintMat-	Prints a matrix for the cross product operation.
;
;		On Entry:
;
;			DS must point at DSEG.
;			DS:SI points at the entry in ResultArrays for the
;			array to print.
;
; The output takes the following form:
;
;	Matrix Title
;
;	       <- column matrix values ->
;
;	^      *------------------------*
;	|      |                        |
;	R      |                        |
;	o      | Cross Product Matrix   |
;       w      |       Values           |
;	       |                        |
;       V      |                        |
;	a      |                        |
;	l      |                        |
;	u      |                        |
;	e      |                        |
;	s      |                        |
;	|      |                        |
;	v      *------------------------*


PrintMat	proc	far
		assume	ds:dseg


; Note the use of conditional assembly to insert extra debugging statements
; if a special symbol "debug" is defined during assembly.  If such a symbol
; is not defined during assembly, the assembler ignores the following
; statements:

		ifdef	debug
		print
		char	"In PrintMat",cr,lf,0
		endif


; First, print the title of this table.  The TTL field in the dope vector
; contains a pointer to a zero terminated title string.  Load this pointer
; into es:di and call PUTS to print that string.

		putcr
		les	di, [si].DopeVec.TTL
		puts

; Now print the column values.  Note the use of PUTISIZE so that each
; value takes exactly six print positions. The following loop repeats
; once for each element in the Column array (the number of elements in
; the column array is given by the Dim2 field in the dope vector).

		print				;Skip spaces to move past the
		char	cr,lf,lf,"       ",0	; row values.

		mov	dx, [si].DopeVec.Dim2	;# of times to repeat the loop.
		les	di, ColArray		;Base address of array.
ColValLp:	mov	ax, es:[di]		;Fetch current array element.
		mov	cx, 6			;Print the value using a
		putisize			; minimum of six positions.
		add	di, 2			;Move on to next array element.
		dec	dx			;Repeat this loop DIM2 times.
		jne	ColValLp
		putcr				;End of column array output
		putcr				;Insert a blank line.

; Now output each row of the matrix.  Note that we need to output the
; RowArray value before each row of the matrix.
;
; RowLp is the outer loop that repeats for each row.

		mov	Rows, 0			;Repeat for 0..Dim1-1 rows.
RowLp:		les	di, RowArray		;Output the current RowArray
		mov	bx, Rows		; value on the left hand side
		add	bx, bx			; of the matrix.
		mov	ax, es:[di][bx]		;ES:DI is base, BX is index.
		mov	cx, 5			;Output using five positions.
		putisize
		print
		char	": ",0

; ColLp is the inner loop that repeats for each item on each row.

		mov	Columns, 0		;Repeat for 0..Dim2-1 columns.
ColLp:		mov	bx, Rows		;Compute index into the array
		imul	bx, [si].DopeVec.Dim2	; index := (Rows*Dim2 +
		add	bx, Columns		;		columns) * 2
		add	bx, bx

; Note that we only have a pointer to the base address of the array, so we
; have to fetch that pointer and index off it to access the desired array
; element.  This code loads the pointer to the base address of the array into
; the es:di register pair.

		les	di, [si].DopeVec.Data	;Base address of array.
		mov	ax, es:[di][bx]		;Get array element

; The functions that compute the values for the array store an 8000h into
; the array element if some sort of error occurs.  Of course, it is possible
; to produce 8000h as an actual result, but giving up a single value to
; trap errors is worthwhile.  The following code checks to see if an error
; occurred during the cross product.  If so, this code prints "  ****",
; otherwise, it prints the actual value.

		cmp	ax, 8000h		;Check for error value
		jne	GoodOutput
		print
		char	"  ****",0		;Print this for errors.
		jmp	DoNext

GoodOutput:	mov	cx, 6			;Use six print positions.
		putisize			;Print a good value.

DoNext:		mov	ax, Columns		;Move on to next array
		inc	ax			; element.
		mov	Columns, ax
		cmp	ax, [si].DopeVec.Dim2	;See if we're done with
		jb	ColLp			; this column.

		putcr				;End each column with CR/LF

		mov	ax, Rows		;Move on to the next row.
		inc	ax
		mov	Rows, ax
		cmp	ax, [si].DopeVec.Dim1	;Have we finished all the
		jb	RowLp			; rows?  Repeat if not done.
		ret
PrintMat	endp
PrintSeg	ends





cseg		segment	para public 'code'
		assume	cs:cseg, ds:dseg


;GetWholeNum-	This routine reads a whole number (an integer greater than
;		zero) from the user.  If the user enters an illegal whole
;		number, this procedure makes the user re-enter the data.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -