📄 ex8.asm
字号:
GetWholeNum proc near
lesi InputLine ;Point es:di at InputLine array.
gets
call Geti ;Get an integer from the line.
jc BadInt ;Carry set if error reading integer.
cmp ax, 0 ;Must have at least one row or column!
jle BadInt
ret
BadInt: print
char Bell
char "Illegal integer value, please re-enter",cr,lf,0
jmp GetWholeNum
GetWholeNum endp
; Various routines to call for the cross products we compute.
; On entry, AX contains the first operand, dx contains the second.
; These routines return their result in AX.
; They return AX=8000h if an error occurs.
;
; Note that the CrossProduct function calls these routines indirectly.
addition proc far
add ax, dx
jno AddDone ;Check for signed arithmetic overflow.
mov ax, 8000h ;Return 8000h if overflow occurs.
AddDone: ret
addition endp
subtraction proc far
sub ax, dx
jno SubDone
mov ax, 8000h ;Return 8000h if overflow occurs.
SubDone: ret
subtraction endp
multiplication proc far
imul ax, dx
jno MulDone
mov ax, 8000h ;Error if overflow occurs.
MulDone: ret
multiplication endp
division proc far
push cx ;Preserve registers we destory.
mov cx, dx
cwd
test cx, cx ;See if attempting division by zero.
je BadDivide
idiv cx
mov dx, cx ;Restore the munged register.
pop cx
ret
BadDivide: mov ax, 8000h
mov dx, cx
pop cx
ret
division endp
; The following function computes the remainder if the symbol "DoMOD"
; is defined somewhere prior to this point.
ifdef DoMOD
modulo proc far
push cx
mov cx, dx
cwd
test cx, cx ;See if attempting division by zero.
je BadDivide
idiv cx
mov ax, dx ;Need to put remainder in AX.
mov dx, cx ;Restore the munged registers.
pop cx
ret
BadMod: mov ax, 8000h
mov dx, cx
pop cx
ret
modulo endp
endif
; If you decide to extend the ResultArrays dope vector array, this is a good
; place to define the function for those new arrays.
; The main program that reads the data from the user, calls the appropriate
; routines, and then prints the results.
Main proc
mov ax, dseg
mov ds, ax
mov es, ax
meminit
; Prompt the user to enter the number of rows and columns:
GetRows: print
byte "Enter the number of rows for the matrix:",0
call GetWholeNum
mov Rows, ax
; Okay, read each of the row values from the user:
print
char "Enter values for the row (vertical) array",cr,lf,0
; Malloc allocates the number of bytes specified in the CX register.
; AX contains the number of array elements we want; multiply this value
; by two since we want an array of words. On return from malloc, es:di
; points at the array allocated on the "heap". Save away this pointer in
; the "RowArray" variable.
;
; Note the use of the "wp" symbol. This is an equate to "word ptr" appearing
; in the "matrix.a" include file. Also note the use of the address expression
; "RowArray+2" to access the segment portion of the double word pointer.
mov cx, ax
shl cx, 1
malloc
mov wp RowArray, di
mov wp RowArray+2, es
; Okay, call "GetArray" to read "ax" input values from the user.
; GetArray expects the number of values to read in AX and a pointer
; to the base address of the array in es:di.
print
char "Enter row data:",0
mov ax, Rows ;# of values to read.
call GetArray ;ES:DI still points at array.
; Okay, time to repeat this for the column (horizontal) array.
GetCols: print
byte "Enter the number of columns for the matrix:",0
call GetWholeNum ;Get # of columns from the user.
mov Columns, ax ;Save away number of columns.
; Okay, read each of the column values from the user:
print
char "Enter values for the column (horz.) array",cr,lf,0
; Malloc allocates the number of bytes specified in the CX register.
; AX contains the number of array elements we want; multiply this value
; by two since we want an array of words. On return from malloc, es:di
; points at the array allocated on the "heap". Save away this pointer in
; the "RowArray" variable.
mov cx, ax ;Convert # Columns to # bytes
shl cx, 1 ; by multiply by two.
malloc ;Get the memory.
mov wp ColArray, di ;Save pointer to the
mov wp ColArray+2, es ; columns vector (array).
; Okay, call "GetArray" to read "ax" input values from the user.
; GetArray expects the number of values to read in AX and a pointer
; to the base address of the array in es:di.
print
char "Enter Column data:",0
mov ax, Columns ;# of values to read.
call GetArray ;ES:DI points at column array.
; Okay, initialize the matrices that will hold the cross products.
; Generate RASize copies of the following code.
; The "repeat" macro repeats the statements between the "repeat" and the "endm"
; directives RASize times. Note the use of the Item symbol to automatically
; generate different indexes for each repetition of the following code.
; The "Item = Item+1" statement ensures that Item will take on the values
; 0, 1, 2, ..., RASize on each repetition of this loop.
;
; Remember, the "repeat..endm" macro copies the statements multiple times
; within the source file, it does not execute a "repeat..until" loop at
; run time. That is, the following macro is equivalent to making "RASize"
; copies of the code, substituting different values for Item for each
; copy.
;
; The nice thing about this code is that it automatically generates the
; proper amount of initialization code, regardless of the number of items
; placed in the ResultArrays array.
Item = 0
repeat RASize
mov cx, Columns ;Compute the size, in bytes,
imul cx, Rows ; of the matrix and allocate
add cx, cx ; sufficient storage for the
malloc ; array.
mov wp ResultArrays[Item * (sizeof DopeVec)].Data, di
mov wp ResultArrays[Item * (sizeof DopeVec)].Data+2, es
mov ax, Rows
mov ResultArrays[Item * (sizeof DopeVec)].Dim1, ax
mov ax, Columns
mov ResultArrays[Item * (sizeof DopeVec)].Dim2, ax
mov ResultArrays[Item * (sizeof DopeVec)].ESize, 2
Item = Item+1
endm
; Okay, we've got the input values from the user,
; now let's compute the addition, subtraction, multiplication,
; and division tables. Once again, a macro reduces the amount of
; typing we need to do at this point as well as automatically handling
; however many items are present in the ResultArrays array.
element = 0
repeat RASize
lfs bp, RowArray ;Pointer to row data.
lgs bx, ColArray ;Pointer to column data.
lea cx, ResultArrays[element * (sizeof DopeVec)]
call CrossProduct
element = element+1
endm
; Okay, print the arrays down here. Once again, note the use of the
; repeat..endm macro to save typing and automatically handle additions
; to the ResultArrays array.
Item = 0
repeat RASize
mov si, offset ResultArrays[item * (sizeof DopeVec)]
call PrintMat
Item = Item+1
endm
; Technically, we don't have to free up the storage malloc'd for each
; of the arrays since the program is about to quit. However, it's a
; good idea to get used to freeing up all your storage when you're done
; with it. For example, were you to add code later at the end of this
; program, you would have that extra memory available to that new code.
les di, ColArray
free
les di, RowArray
free
Item = 0
repeat RASize
les di, ResultArrays[Item * (sizeof DopeVec)].Data
free
Item = Item+1
endm
Quit: ExitPgm ;DOS macro to quit program.
Main endp
cseg ends
sseg segment para stack 'stack'
stk byte 1024 dup ("stack ")
sseg ends
zzzzzzseg segment para public 'zzzzzz'
LastBytes byte 16 dup (?)
zzzzzzseg ends
end Main
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -