The MASM Forum

Miscellaneous => 16 bit DOS Programming => Topic started by: brettc431 on April 18, 2013, 12:35:02 AM

Title: Reduced Row-Echelon Form of a Matrix Help
Post by: brettc431 on April 18, 2013, 12:35:02 AM
Before I get started on the help I need I will say that yes this is a project for school so I'm not looking for anyone to give me the code but my group is new to MASM and struggling to get the code.  We understand how to find the RREF on paper, but not through code.  Here is our assignment:

Row-Echelon Matrix Reduction
Write a program that calculates the row-echelon form of a matrix of any size. The matrix values are all integer and stored in an input file. The reduced matrix is stored in an output file. The values of the output matrix should also be integer values.


And here is our current code, it's bad we know:

.MODEL SMALL ;Defines memory model as small which uses separate segments for code and data
.386 ;Microprocessor number
.STACK ;Stack segment defined as 1024 by default
.DATA ;Begins definition of the data type used in this project

ROW DB ?
COLUMN DB ?
RREF DB "matrix.txt", 0

.CODE

;-------------------------------------------------------------------------------------------
READ MACRO
MOV CX, LENGTHOF RREF
MOV DX, OFFSET RREF
MOV AH, 3FH ;Read
INT 21H
JC QUIT
CMP AX, 1
JNE QUIT

;-------------------------------------------------------------------------------------------

Main PROC FAR ;Defines procedure distance as far
.STARTUP 
;Program:

MOV BP, 0
MOV SI, 0

MOV AX, 3D02h ;Open file
MOV DX, OFFSET RREF
INT 21H
MOV BX, AX


IF ROW<COLUMN
D=ROW
IF ROW>COLUMN
D=COLUMN
FOR d=1...D
e=M(d,d)
FOR r=d...(ROW-1)
X=M(ROW,d)/e
FOR col=d...COLUMN
M(r,col)=M(r,col)-e*X





PUSH BP

MOV BP, SP

CALL REDUCTION
JC QUIT
ADD SP 2+4
POP BP


MOV AH,40h
INT 21H

MOV AH, 3Eh
INT 21H

QUIT: .EXIT
MAIN ENDP


REDUCTION PROC
PUSHAD

MOVZX EAX, ROW
MOV EDX, EAX
MOVZX EBX, COLUMN
SUB EBX, 1
MUL EBX
JC QUIT
SUB EDX, 1
ADD EAX, EDX

JC QUIT
LOOP
POPAD
RET
REDUCTION ENDP

END


The code itself is all over the place.  We have to open a file from MATLAB containing a matrix in the form [R,C,#,#,#,#,#,#,#,#,#,#, etc.] where the first two bytes are the row and column numbers respectively, and the rest are the elements of the matrix stored in 8 bytes each.  The matrix can go all the way to R-C dimensions of 255,255 but that is randomly generated in MATLAB.  Once we open and read the file, we have to calculate the reduced row echelon form with only the elements below the diagonal zeroed out, everything above the diagonal doesn't matter.  Then we must write the RREF matrix to an output file to be opened in MATLAB and displayed.

Any and all help will be greatly appreciated, we just need to be steered in the right direction.  Here is our trouble:

1. How to read two separate bytes, then each element, which are 8 bytes long a piece, and what to do with them
2. How to code for reducing the lower half of the matrix
3. How to write to an output file

Programs we are using are Textpad 6 and Codeview debugger
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: FORTRANS on April 18, 2013, 04:28:48 AM
Hi,

Quote1. How to read two separate bytes,

   Using parts of your code, it would look something like the
following.


        MOV     CX,2    ; Want to read two bytes.
        MOV     DX, OFFSET ROW
        MOV     AH, 3FH ;Read
        INT     21H
        JC      QUIT
        CMP      AX, 2
        JNE     QUIT


   That will place one byte in ROW and one in COLUMN.

Quotethen each element, which are 8 bytes long a piece

   Well, change the 2 to an 8 in the above code and point to an
element buffer, and you can read them in one at a time.  Or
multiply the row times the column times 8 and read them in all at
once.  Remember to allocate enough space to hold the whole lot.

Quoteand what to do with them

   Find the MATLAB documentation and find what format the
elements are stored in.  Real4 and integers are possible.

Regards,

Steve N.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: jj2007 on April 18, 2013, 05:19:05 AM
Quote from: FORTRANS on April 18, 2013, 04:28:48 AM
   Find the MATLAB documentation and find what format the
elements are stored in.  Real4 and integers are possible.

MatLab is normally REAL8 aka "double". However, two bytes for rows and columns at the beginning is not a standard MatLab matrix. Only your supervisor knows what format that is. My best guess is 2 bytes R+C plus REAL8 elements. Which is a lousy format for performance reasons (badly aligned) but technically it can work, if you have no more that 256 rows...
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: FORTRANS on April 18, 2013, 07:14:05 AM
Quote from: jj2007 on April 18, 2013, 05:19:05 AM
MatLab is normally REAL8 aka "double".

Hi,

   Yes, my mistake.  Thanks for the correction.

QuoteHowever, two bytes for rows and columns at the beginning is not a standard MatLab matrix. Only your supervisor knows what format that is. My best guess is 2 bytes R+C plus REAL8 elements. Which is a lousy format for performance reasons (badly aligned) but technically it can work, if you have no more that 256 rows...

   At any rate, they need to know what the elements in the file
are.  And I would hope no more than a 10x10 matrix.  I would
not think alignment in the file would hurt amything?  Alignment
in memory can hurt.  But if getting a working program is the
goal, I would leave that to last to worry about.

Regards,

Steve N.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: RuiLoureiro on April 18, 2013, 07:34:25 AM
Quote from: jj2007 on April 18, 2013, 05:19:05 AM
Quote from: FORTRANS on April 18, 2013, 04:28:48 AM
   Find the MATLAB documentation and find what format the
elements are stored in.  Real4 and integers are possible.

MatLab is normally REAL8 aka "double". However, two bytes for rows and columns at the beginning is not a standard MatLab matrix. Only your supervisor knows what format that is. My best guess is 2 bytes R+C plus REAL8 elements. Which is a lousy format for performance reasons (badly aligned) but technically it can work, if you have no more that 256 rows...
Jochen, he said each element of matrix is 8 bytes, not real 8.
                read it again else where [R, C ...]... :icon14:
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: brettc431 on April 18, 2013, 07:39:29 AM
Quote from: FORTRANS on April 18, 2013, 04:28:48 AM

Quoteand what to do with them

   Find the MATLAB documentation and find what format the
elements are stored in.  Real4 and integers are possible.


Thanks for the help so far.  The matrix elements in the input and output file are both stored as integers.  The max matrix size, as told by our instructor, will be 255x255.  Our code needs to be able to read the row and column inputs, decide which of the values is smaller so that the correct diagonal can be setup, then loop all the way through the matrix beneath the diagonal to zero-out the elements.

Also, the file format is 2 bytes (R & C) then all the elements separated by one space each.  i.e. R C (element) (element) (element) (element) (element) etc.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: FORTRANS on April 19, 2013, 12:02:28 AM
Quote from: brettc431 on April 18, 2013, 07:39:29 AM
Thanks for the help so far.  The matrix elements in the input and output file are both stored as integers.  The max matrix size, as told by our instructor, will be 255x255.  Our code needs to be able to read the row and column inputs, decide which of the values is smaller so that the correct diagonal can be setup, then loop all the way through the matrix beneath the diagonal to zero-out the elements.

Also, the file format is 2 bytes (R & C) then all the elements separated by one space each.  i.e. R C (element) (element) (element) (element) (element) etc.

Hi,

   Well the two bytes for row and column are obviously binary
values if they can be as large as 255.  Elements separated by
spaces sounds a bit odd.  Are the integers ASCII (text) or
binary?  Are the spaces part of the eight bytes or are there nine
bytes per matrix entry?  These questions are minor considerations
anyway.  Reading the data into your program should be relatively
easy.

   Just reading the file into memory and writing it back out
would be a good starting point.

   As far as the processing of the matrix, assuming there are
more than one of you, have one play dumb at a black board,
or a piece of paper, and have the rest walk through the algorithm
telling the victim what to do.  Write down pseudo-code (or a
computer language you are familar with) to map out your
program logic.  For example, use a grid of eight boxes for the
CPU registers.  And another grid for locations in memory.
Another grid of eight boxes for the FPU registers, if needed
(that would be rather advanced).  Write out a list of opcodes
that you are expected to use to help in telling someone what
to do.

   What programming environment are you using?  Do you
have a library of routines available?  For ASCII to binary number
conversion for instance.  What text book is the class using?

Regards,

Steve
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: jj2007 on April 19, 2013, 12:47:33 AM
Quote from: RuiLoureiro on April 18, 2013, 07:34:25 AMJochen, he said each element of matrix is 8 bytes, not real 8.

Rui, I had seen that and guessed that it was binary data, so 8 bytes = real8. But (see recent posts) it could also be text.

Brett, the best way to get clarity about the format is to post a sample "database". Just zip it and attach it.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: RuiLoureiro on April 19, 2013, 03:58:18 AM
Quote from: brettc431 on April 18, 2013, 07:39:29 AM
Quote from: FORTRANS on April 18, 2013, 04:28:48 AM

Quoteand what to do with them

   Find the MATLAB documentation and find what format the
elements are stored in.  Real4 and integers are possible.


Thanks for the help so far.  The matrix elements in the input and output file are both stored as integers.  The max matrix size, as told by our instructor, will be 255x255.  Our code needs to be able to read the row and column inputs, decide which of the values is smaller so that the correct diagonal can be setup, then loop all the way through the matrix beneath the diagonal to zero-out the elements.

Also, the file format is 2 bytes (R & C) then all the elements separated by one space each.  i.e. R C (element) (element) (element) (element) (element) etc.

Hi brettc431,
                     I could help you but only and if only it was written in 32 bits
In this forum we may find "The calculator" that does matrix and you may find
also a library Math10 where you may find procedures to convert string to real and real to string. I already wrote code for matrix, all operations in real4, real8, real10, integer32 and integer64 but i need time to test all that work.
                   In "Campus" you can see the topic: "converting string to real4" and you can download the zip file. You will find a good procedure to convert string to real 4 in 32 bits
:icon14:
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: brettc431 on April 19, 2013, 08:23:05 AM
I've got a partner working on the open, read, write, and close.  I'm working on the algorithm for reducing the matrix.

Here's what I've got so far but I don't know how to implement this into code:

Say the matrix is:

M    =    1   2   3   4
      5   6   7   9
      10   11   12   13


Algorithm for reducing the matrix:
1.    Determine the number of diagonal elements 

2.   Create a loop that goes through the diagonal elements

3.   Read a diagonal element M(I,I) and the one next to it. The one next to it will the next element in the row below it. Use M[d*8+2] to get the diagonal element. Save both into variables: e=M(I,I) and ep1=M(I+1,I).

E.g. the first diagonal element is M(1,1), d = (1-1)*3+1-1=0 => M(1,1)=M[0*8+2]=M[2]. Move the file pointer to 2. Read 8 bytes into variable e. Then read another 8 bytes in ep1.

We want to perform the row subtraction for an entire row starting with the element under the diagonal and ending with the last column of the row

Also, we must scale the row subtraction to give 0 underneath the diagonal. Scale = -e/ep1.

E.g. for M(1,1) = 1; M(2,1) = 5; scale = -1/5.

Set r= I+1 = 2, set c = I=1.
M(r,c) = M(r,c)*scale + M(I,I)       ;read M(r,c) by calculating M[8*d+2]
Write M(r,c) in the output file       ;requires that the output file be initialized.
c = c+1
Repeat until c = Col = 4.

What this would do is
   M(2,1)= 5(-1/5) + 1 = 0
   M(2,2)= 6(-1/5) + 2 = -4/8
   M(2,3)= 7(-1/5) + 3 = -8/5
   M(2,4)= 8(-1/5) + 4 = -12/5

By initialized output file, I mean that the output file is not blank. This can be done by copying the input file into the output, or writing zero's equivalent to the size of the input file into the output file.

4.   Make the diagonal M(I,I)=1. Divide the entire row of the diagonal by the value in the diagonal.
E.g. for the first diagonal element:
Set r=I=1, set c=I=1
   M(r,c) = M(r,c)/e         ; read M(r,c) by calculating M[8*d+2]
Write M(r,c) in the output file       ;requires that the output file be initialized.
c = c+1
Repeat until c = Col = 4.

Step 4 is carried out after step 3 because it will be faster that way.

5.   Loop to step 3.


Any help on the code itself?  Even just a basic format would be a help at this point.  The project has to be running by monday evening.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: dedndave on April 19, 2013, 08:48:56 AM
QuoteI've got a partner working on the open, read, write, and close.  I'm working on the algorithm for reducing the matrix.

he got the better end of that deal - lol
(tell him to look up INT 21h, functions 3Ch, 3Dh, 3Eh, 3Fh, and 40h)

as Jochen mentioned....
http://masm32.com/board/index.php?topic=1813.msg18636#msg18636 (http://masm32.com/board/index.php?topic=1813.msg18636#msg18636)
it would make things easier if we could see an example database
that's not because of read and write
it's because we want to see the numeric format
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: brettc431 on April 19, 2013, 09:11:11 AM
I'm not sure what you're asking for,  I am a total beginner to masm.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: dedndave on April 19, 2013, 09:13:44 AM
what we would like to see is an example file from MATLAB
you can attach ZIP files to your post by clicking on the "Attachments and other options" link under the reply window

we need to see exactly how the values are stored in the file
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: brettc431 on April 19, 2013, 09:20:24 AM
This is what the instructor sent us:

E.g. If the matrix is M = [
1.0 2.0 3.0
4.0 5.0 6.0
7.0 8.0 9.0]

Then input file will contain: 3,3,1.0,4.0,7.0,2.0,5.0,8.0,3.0,6.0,9.0

Note that the first 2 values are R and C, and the remaining values are the elements organized by columns. The values in hex will be:

03,03,3FF0000000000000,4010000000000000,401C000000000000,4000000000000000,4014000000000000,4020000000000000,4008000000000000,4018000000000000,4022000000000000

Matlab commands:
M = [1 2 3; 4 5 6; 7 8 9]; %creates a 3x3 matrix
[r c] = size(M);                %find size of M
mvec = reshape(M,1,r*c);         %converts matrix into a vector of columns
fid = fopen('inputfile','w')    %opens a file to store mvec into
fwrite(fid,[r c],'uint8')        %store the row and column a byte values
fwrite(fid,mvec, 'double')              %Store as double precision values
fclose(fid)                   %close file



We are to use the above MATLAB commands to create a matrix with random elements, then reduce it through masm.  I know it isn't a database, but I do not have MATLAB on my personal computer at home.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: dedndave on April 19, 2013, 10:14:27 AM
that is probably enough info for us to work with   :t
assuming the values are stored in binary   :P

the row and column values are "unsigned byte integers"
the matrix values are "real8 floating point" format, also known as double precision

we can align the data by aligning to 4 or 8, then padding the buffer with 2 or 6 bytes to align the reals
i.e., read data to buffer+2 or buffer+6
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: dedndave on April 19, 2013, 10:29:59 AM
i haven't done much of this type stuff, but it doesn't look too difficult

http://en.wikipedia.org/wiki/Gauss%E2%80%93Jordan_elimination (http://en.wikipedia.org/wiki/Gauss%E2%80%93Jordan_elimination)

QuoteThere are three types of elementary row operations: 1) Swapping two rows, 2) Multiplying a row by a
non-zero number, 3) Adding a multiple of one row to another row. Using these operations a matrix can
always be transformed into an upper triangular matrix, and in fact one that is in row echelon form.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: FORTRANS on April 20, 2013, 12:32:03 AM
Hi,

   Since the matrix elements are floating point numbers, you
will need to use the FPU or SSE instructions.  And your
instructor should have routines to print the numbers out.

Cheers,

Steve N.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: dedndave on April 20, 2013, 01:58:41 AM
Steve,
the assignment is merely to re-order the matrix
they are using MATLAB to generate the original matrix - and to display the results
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: FORTRANS on April 20, 2013, 02:18:03 AM
Hi Dave,

   He's going to do the stuff in Reply #9 without adding, subtracting,
and comparing floats?

Cheers,

Steve N.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: dedndave on April 20, 2013, 03:52:18 AM
no - but he doesn't have to convert them to decimal   :P

the hard part will be the compares

QuoteAnd your instructor should have routines to print the numbers out.
MATLAB
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: brettc431 on April 21, 2013, 07:21:55 AM
Worked on the code a bit this morning so here's another look:

.MODEL SMALL ;Defines memory model as small which uses seperate segments for code and data
.386 ;Microprocessor number
.STACK ;Stack segment defined as 1024 by default
.DATA ;Begins definition of the data type used in this project

row DB ?
col DB ?
e DW ?
ep1 DW ?
D DB ?
d DW ?
ROW DB ?
COLUMN DB ?
M DW 65025 DUP(?)
RREF DB "matrix", 0


.CODE
MAIN PROC FAR
.STARTUP
;Program:

MOV BP, 0
MOV SI, 0

MOV AX, 3D02h ;Open file
MOV DX, OFFSET RREF
INT 21H
MOV BX, AX

MOV     CX,1    ;Read two bytes.
MOV     DX, OFFSET ROW
MOV     AH, 3FH ;Read
INT     21H
JC      QUIT
    CMP      AX, 1
        JNE     QUIT
       
        MOV     CX,8    ;Read eight bytes.
MOV     DX, OFFSET M
MOV     AH, 3FH ;Read
INT     21H
JC      QUIT
    CMP      AX, 8
JNE     QUIT

        IF (ROW LT COLUMN)
        MOV D, ROW
   
        ELSEIF (ROW GT COLUMN)
        MOV D, COLUMN
        ENDIF
       
        MOV row, D
        MOV col, D
       
           
       
       
        MOV AX, d
        MOV BX, 8
        MUL BX
        ADD AX, 2 ;M[d] = d*8+2
       
       
        MOV EAX, 0
       
       
       
        ;d=(col-1)*ROW+(row-1)
        MOV AL, col ;Determine number of diagonals
        SUB AL, 1
        MOV BL, row
        MOV DL, BL
        SUB BL, 1
        MUL DL
        ADD AX, BL
        MOV d, AX
       
        ;e=M(I,I)
        ;ep1=M(I+1,I)
       
       
        MOV SI, LENGTHOF M
        MOV EAX, M[SI]
        MOV EBX, M[SI+1] ;Now I'm Stuck
       
       
       
       
       
       
       
QUIT:  .EXIT
MAIN    ENDP
      END


I created an array with a length of 65025 dup (?) to account for a max value of 255x255.  The code is in no particular order but I'm following the algorithm the instructor gave us from a few posts up.  Am I completely lost or am I least on the right track?  I know it has a lot left to be a working code but I'm struggling with the language and how to put the algorithm into code.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: brettc431 on April 22, 2013, 04:34:02 AM
I haven't made any progress since my last post and the code has to be working by tomorrow evening.  We are beginning to feel like it won't get done on time since we are having so much trouble with the language itself.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: dedndave on April 22, 2013, 04:54:53 AM
you seem to understand the concept of what the program needs to do

what you don't understand is the FPU code
i suggest you read Ray's FPU tutorial
http://www.ray.masmcode.com/fpu.html (http://www.ray.masmcode.com/fpu.html)

you don't need to use all the FPU instructions - so you won't need to understand the entire tutorial
but, you do need to understand how to use the FPU registers (aka stack)
you need to know how to get numbers into and out of the FPU
you need to know how to add, subtract, multiply, and compare

so, chapters 1-4 and 7-8 should get you going
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: jj2007 on April 22, 2013, 06:02:25 AM
Given that you have little time, study in the attachment:
fld
fst
fadd, fsub, fmul, fdiv (whatever you need)

On the net, read about fcomi (http://www.website.masmforum.com/tutorials/fptute/fpuchap7.htm#fcomi) (compare)

Dave's advice is valid, too, of course - maybe you can split the work. What I attach is the barebones of FPU work, what Dave suggests is more thorough.

Good luck :icon14:
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: FORTRANS on April 22, 2013, 06:03:31 AM
Hi,

MOV     CX,1    ;Read two bytes.

   Your comment says to read two bytes.  You are only reading one.
Either make another read section to read in one byte into the column
variable.  Or actually read two bytes to fill both row and columns.
This affects all further reads from the file and they will all be off one
byte.  And thus a bit wrong.

Steve
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: brettc431 on April 22, 2013, 08:21:53 AM
FORTRANS, that was an error on my partner's part, it should have the number 2.

Thanks everyone for the help with FPU.  I'm reviewing it now and should hopefully have some more code in the thread in a little while.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: dedndave on April 22, 2013, 10:50:20 AM
the FPU registers will hold 8 values, and are typically addressed as a last-in-first-out stack
the stack top is refered to as ST(0), or just ST
the others are refered to as ST(1) to ST(7)
some operations allow you to perform an arithmetic function and "pop" the stack into memory, in a single instruction (FADDP for example)

if all the registers are full, and you try to load a new value, an exception will occur
not only will the results of the next operation be incorrect, but the code will execute very slowly
this is one thing that catches many beginners   :P
half the trick of writing FPU code is to keep track of what is where in the register stack

i like to think of the register stack as an 8-shot revolver cylinder

(http://img35.imageshack.us/img35/2574/fpuregs.jpg)

a few instructions are intended for managing the stack

FFREE marks a register as empty, so that it may be loaded with a new value
notice that you can FFREE ST(7) to make room for a new value in ST(0)
the old ST(0) value becomes ST(1), the old ST(1) value becomes ST(2), and so on

FDECSTP and FINCSTP allow you to rotate the "cylinder" to select which value will be on the stack top
very handy

FFREE, FDECSTP, and FINCSTP are discussed in chapter 3 of Ray's tutorial
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: brettc431 on April 22, 2013, 01:01:52 PM
Here's some more code.  No real progress:

.MODEL SMALL ;Defines memory model as small which uses seperate segments for code and data
.386 ;Microprocessor number
.STACK ;Stack segment defined as 1024 by default
.DATA ;Begins definition of the data type used in this project

row DB ?
col DB ?
e DW ?
ep1 DW ?
D DB ?
d DW ?
ROW DB ?
COLUMN DB ?
M DW 65025 DUP(?)
RREF DB "matrix", 0


.CODE
MAIN PROC FAR
.STARTUP
;Program:

MOV BP, 0
MOV SI, 0

MOV AX, 3D02h ;Open file
MOV DX, OFFSET RREF
INT 21H
MOV BX, AX

MOV     CX,2    ;Want to read two bytes.
MOV     DX, OFFSET ROW
MOV     AH, 3FH ;Read
INT     21H
JC      QUIT
    CMP      AX, 2
        JNE     QUIT
       
        MOV     CX,8    ;Want to read eight bytes.
MOV     DX, OFFSET M
MOV     AH, 3FH ;Read
INT     21H
JC      QUIT
    CMP      AX, 8
JNE     QUIT

        IF (ROW LT COLUMN)
        MOV D, ROW
   
        ELSEIF (ROW GT COLUMN)
        MOV D, COLUMN
        ENDIF
       
        MOV row, D
        MOV col, D
       
           
       
       
        ;MOV AX, d
        ;MOV BX, 8
        ;MUL BX
        ;ADD AX, 2 ;M[d] = d*8+2
       
       
        MOV EAX, 0
       
       
       
        MOV SI, D ;d=(col-1)*ROW+(row-1)
    L1:    MOV AL, col ;Determine number of diagonals
        SUB AL, 1
        MOV BL, row
        MOV DL, BL
        SUB BL, 1
        MUL DL
        ADD AX, BL
        MOV d, AX
       
        ;e=M(I,I)
        ;ep1=M(I+1,I)
       
        MOV EAX, M[d*8+2]
        MOV e, EAX
       
       
        MOV AL, col
SUB AL, 1
MOV BL, row
ADD BL, 1
MOV DL, BL
SUB BL, 1
MUL DL
ADD AX, BL
        MOV d, AX
       
        MOV EBX, M[d*8+2]
        MOV ep1, EBX
       
        ADD row, 1
        MOV col, 1
       
               
        FINIT
        FLD1
        FLD1
        FADD ST(1), ST(1)
        CMP ST(1), ep1
        JE SKIP
L2:        FADD ST(1), ST
        CMP ST(1), ep1
        JNE L2
SKIP: FCHS
FDIVR
       
       
       
       
       
QUIT:  .EXIT
MAIN    ENDP
      END
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: FORTRANS on April 22, 2013, 11:16:33 PM
Hi,

   To compare registers in the FPU to something, use FCMP rather
than CMP, which is for the CPU registers or memory.


        CMP ST(1), ep1
test43.asm(108) : error A2152: coprocessor register cannot be first operand


   You also have some symbols defined more than once.  Make a
listing to check for errors.


ROW DB ?
test43.asm(12) : error A2005: symbol redefinition : row


HTH,

Steve N.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: jj2007 on April 23, 2013, 12:15:13 AM
Quote from: FORTRANS on April 22, 2013, 11:16:33 PM
To compare registers in the FPU to something, use FCMP rather
than CMP, which is for the CPU registers or memory.

Quote from: jj2007 on April 22, 2013, 06:02:25 AM
On the net, read about fcomi (http://www.website.masmforum.com/tutorials/fptute/fpuchap7.htm#fcomi) (compare)

AFAIK there is no FCMP (there is a MasmBasic Fcmp (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1201), though). FCOM works but it is difficult to handle, as it does not set the EFLAGS as we are expect them. Therefore FCOMI seems the easiest solution - if it works in 16-bit code and on the group's CPU, of course.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: FORTRANS on April 23, 2013, 01:06:43 AM
Hi,

   Yes, I meant FCOM, or FCOMP, but was looking at CMP.
Or FCOMI of course, though I rarely remember that one,
though it should work.

Thanks,

Steve N.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: brettc431 on April 23, 2013, 09:50:25 AM
New code:

.MODEL SMALL ;Defines memory model as small which uses seperate segments for code and data
.386 ;Microprocessor number
.STACK ;Stack segment defined as 1024 by default
.DATA ;Begins definition of the data type used in this project

A DD ?
B DD ?
S DD ?
row DB ?
col DB ?
e DD ?
ep1 DD ?
M DD LENGTHOF row*LENGTHOF col DUP(?)
RREF DB "matrix", 0



;-------------------------------------------------------------------------------
calcoffset MACRO row, col 
PUSH EDI, ESI
MOV ESI, row
MOV EDI, col
DEC EDI
MUL EDI
ADD EAX, ESI
DEC EAX ;M[EAX]
POP EDI, ESI
ENDM
;-------------------------------------------------------------------------------

.CODE
MAIN PROC FAR
.STARTUP
;Program:

MOV BP, 0
MOV SI, 0

MOV AX, 3D02h ;Open file
MOV DX, OFFSET RREF
INT 21H
MOV BX, AX

MOV     CX,2    ;Want to read two bytes.
MOV     DX, OFFSET ROW
MOV     AH, 3FH ;Read
INT     21H
JC      QUIT
    CMP      AX,2
        JNE     QUIT
       
        MOV     CX,8    ;Want to read eight bytes.
MOV     DX, OFFSET M
MOV     AH, 3FH ;Read
INT     21H
JC      QUIT
    CMP      AX, 8
JNE     QUIT

MOV ESI, 1
MOV EDI, 1
MOVZX EAX, row



MOV ECX, ESI
MOV EBP, 1
DEC ECX
L1: calcoffset EBP, EBP
MOV EDX, M[EAX]
MOV e, EDX
INC ESI
MOV ESI, EBP
MOV EDI, EBP
calcoffset ESI, EBP
MOV EDX, M[EAX]
MOV ep1, EDX
;calc scale to fpu
FINIT
FLD e
FLD ep1
FDIV
FST S


L2: calcoffset ESI, EDI
MOV EDX, M[EAX]
MOV A, EDX

;fpu to calc A*scale+e
FINIT
FLD A
FLD S
FMUL
FLD e
FADD
FST B


INC EDI
MOVZX EDX, col
CMP EDI, EDX
JBE L2
INC ESI
MOVZX EDX, row
CMP ESI, EDX
JBE L2
LOOP L1

     
       


        MOV AH,40h
INT 21H

MOV AH, 3Eh
INT 21H
       
       
       
QUIT:  .EXIT
MAIN    ENDP
      END


Getting syntax errors when attempting to call our macro calcoffset, it's claiming the apostrophe between our register values in the program itself is an issue.  What could be causing this?
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: dedndave on April 23, 2013, 10:01:53 AM
i don't see a syntax error
maybe you could give us the exact error text
we are pretty familiar with what problems cause what errors

i do see something that is going to give you trouble
the "M" array is going to be 1*1 bytes
i think you want it to be 255*255*8 bytes   :P

as a suggestion, use more descriptive names for variables - single-letter names make it hard to follow
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: qWord on April 23, 2013, 10:13:24 AM
as a hint, do not call the macro in a line that contains a label. The reason is that MASM expand macros before the current line thus the label will be placed after the macro code.
Your code:
L2: calcoffset ESI, EDI
and that's how MASM handle it:
calcoffset ESI, EDI
L2:
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: brettc431 on April 23, 2013, 10:32:43 AM
Corrected the syntax errors so I'm all good there. Literally putting 255*255*8 (520200) for the M value returns:

Assembling: final.asm
final.asm(137) : error A2103: segment exceeds 64K limit : _DATA
Press any key to continue . . .
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: dedndave on April 23, 2013, 10:36:01 AM
oh yah - i forgot - lol
you are writing 16-bit code - doh !
also - it didn't dawn on me that that is almost 512 K - could be a tight fit

you will have to do a little memory management
i think, for an EXE, you have to release memory above the program address
then, you can allocate it with INT 21h
actually, i think you own the memory already, but you cannot allocate until you release

it may help to add .DOSSEG at the beginning of the program
that will make the stack segment the highest used address
and, you can use SS:StackSize to calculate the release address
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: brettc431 on April 23, 2013, 10:44:08 AM
We haven't been taught .DOSSEG or SS:Stacksize so if we had it in our project, he'd start asking questions lol
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: dedndave on April 23, 2013, 10:55:18 AM
at the beginning of your program you have a .STACK directive
just use
        .STACK  4096
or how ever many bytes you want
thing is - you will know the stack size
i could look up the default, but i am too lazy - lol
at any rate, you can use SS:[4096] as a release address for memory
        mov     ax,ss
        add     ax,4096/16
;AX = release segment address


another directive is .DOSSEG
        .DOSSEG
all it does is ensure the use of DOS segment ordering - no biggy, there
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: MichaelW on April 23, 2013, 06:17:41 PM
If you are using a small memory model and the startup directive, then you can calculate the actual memory footprint, in paragraphs, as:

PSP_Segment - (SS + (Initial_SP SHR 4) + 1


To understand the above calculation you probably need to know that the startup directive combines the stack and near data segments into a single segment known as DGROUP and places it at the end of the program (where "end" means at the highest address), sets DS and SS to the segment address of DGROUP, and sets SP to the end of the stack (where, again, "end" means at the highest address), and that a paragraph is 16 bytes.

Once you have the size in paragraphs, you pass it to the Set Memory Block Size function (Interrupt 21h Function 4Ah) in BX, along with the segment address of the memory block to resize, which in this case will be the segment address of the PSP, in ES. You can get the segment address of the PSP by any of several methods, but since the program loader will have initialized ES to the segment address of the PSP, you can just pass ES as is.

Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: FORTRANS on April 23, 2013, 10:25:17 PM
Quote from: dedndave on April 23, 2013, 10:36:01 AM
you will have to do a little memory management
i think, for an EXE, you have to release memory above the program address
then, you can allocate it with INT 21h
actually, i think you own the memory already, but you cannot allocate until you release

Hi,

   There is no need to release memory just to allocate again.  It
is allocated to you at program start-up by default.  Just use it.
Find/put a symbol at the end of your code, and verify it is at the
end with a listing of the load map.  At run time you check the
current address in memory of that symbol and compare it with
the next paragraph value in the PSP  (it is the second word).
Those then  tell you how much memory is available for you to use.

   You can address much more than 64k that way.  It seems a bit
out of order though for a beginner to play with.  Perhaps Fn 42H,
Move File Pointer (also known as LSEEK) would be easier?  That
gives the user random access into the file.

   I think if he can get it to work with an 8 x 8 (10?) matrix, then
he can claim it would work for a larger matrix later.

Regards,

Steve N.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: brettc431 on April 23, 2013, 10:31:38 PM
The instructor told us if we put our matrix into memory, it would limit the matrix size but he did not say we would be penalized for it.  He also gave the class an extension until Thursday afternoon to get the code running.  Only thing left for me to get working is the command tail and then I need to start checking that everything is working:


.MODEL SMALL ;Defines memory model as small which uses seperate segments for code and data
.386 ;Microprocessor number
.STACK ;Stack segment defined as 1024 by default
.DATA ;Begins definition of the data type used in this project

mrc DD ?
scale DD ?
D DD ?
row DB ?
col DB ?
e DD ?
ep1 DD ?
M DD 10000 DUP(?)
INPUT DB "input", 0
OUTPUT DB "output", 0



;-------------------------------------------------------------------------------------
;calcoffset takes two input variables and calculates the equation: (op2-1)*op1+(op1-1)
;The value is returned into M[EAX]
;-------------------------------------------------------------------------------------
calcoffset MACRO op1, op2 
PUSH ESI
PUSH EDI
MOV ESI, op1
MOV EDI, op2
DEC EDI
MUL EDI
ADD EAX, ESI
DEC EAX ;M[EAX]
POP EDI
POP ESI
ENDM
;------------------------------------------------------------------------------------

.CODE
MAIN PROC FAR
.STARTUP
;Program:

PUSHAD
MOV EAX, 0h
MOV AH, 62h
INT 21H
MOV ES, BX

MOV SI, 81h
CMP BYTE PTR ES: [SI-1], 1
JBE NO_TAIL

NO_TAIL: MOV DL, 0Ah
INT 21H
MOV DL, 0Dh
INT 21H

MOV BP, 0
MOV SI, 0

MOV AX, 3D02h ;Open file
MOV DX, OFFSET INPUT
INT 21H
MOV BX, AX

MOV     CX,2    ;Want to read two bytes.
MOV     DX, OFFSET D
MOV     AH, 3FH ;Read
INT     21H
JC      QUIT
    CMP     AX,2
        JNE     QUIT
       
        MOV     CX,8    ;Want to read eight bytes.
MOV     DX, OFFSET M
MOV     AH, 3FH ;Read
INT     21H
JC      QUIT
    CMP     AX, 8
JNE     QUIT

MOV ESI, 1
MOV EDI, 1
MOVZX EAX, row



MOV ECX, ESI
MOV EBP, 1
DEC ECX
L1:
calcoffset EBP, EBP
MOV EDX, M[EAX]
MOV e, EDX
INC ESI
MOV ESI, EBP
MOV EDI, EBP
calcoffset ESI, EBP
MOV EDX, M[EAX]
MOV ep1, EDX

;calc scale to fpu
FINIT
FLD e
FLD ep1
FDIV
FST scale
JMP L2

RETURN: JMP L1

L2:
calcoffset ESI, EDI
MOV EDX, M[EAX]
MOV mrc, EDX

;fpu to calc mrc*scale+e
FINIT
FLD mrc
FLD scale
FMUL
FCHS
FLD e
FADD
FST mrc

INC EDI
MOVZX EDX, col
CMP EDI, EDX
JBE L2
INC ESI
MOVZX EDX, row
CMP ESI, EDX
JBE L2
JMP RETURN

     
       

MOV AX, 3D02h
MOV DX, OFFSET OUTPUT
INT 21H
MOV BX, AX
MOV CX, LENGTHOF M
MOV DX, LENGTHOF M
        MOV AH, 40h
INT 21H

MOV AH, 3Eh
INT 21H
       
       
       
QUIT:  .EXIT
MAIN    ENDP
      END
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: dedndave on April 24, 2013, 12:32:30 AM
in the END directive, you should reference the entry point
        END     MAIN

i am not sure what the .STARTUP directive does - never used it
i suppose it loads the DS register with the _DATA segment
so, it probably generates code that looks like this
        mov     ax,@data
        mov     ds,ax


however, when a 16-bit EXE loads, the DS and ES registers contain the PSP (Program Segment Prefix) Segment
it may be a good idea to store this segment value for later reference
        mov     PspSeg,es   ;PspSeg is a word variable

the PSP is a 256-byte segment of information specific to the program execution
it holds things like a pointer to the environment table, parsed filenames, and so on

the last 128 bytes of the PSP hold the command line tail
at PSP:80h, there is a byte value telling you the length of the command line tail string
at PSP:81h is the actual command line tail - it is typically terminated with a carriage return
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: MichaelW on April 24, 2013, 04:48:39 AM
The safe, simple way for a beginner to get a maximum-size memory buffer is to release the excess memory as above and then allocate a maximum-size block with the Allocate Memory function (Interrupt 21h Function 48h). With the way Microsoft designed the function you call it twice, passing a size larger than the largest possible, -1 is handy, in BX on the first call, and then use the size of the largest available block, returned in BX, in the next call. No need to understand memory control blocks, load maps, etc. Running under the Windows XP NTVDM with a default configuration and a relatively small test app I can allocate 629600 bytes.

And it's possible to use a linear index to access the buffer in whatever element size you need, translating the index to a segment-offset address for each access. Reloading a segment register for each access will slow the code down, but it's simple and easy to do and I would guess that the access would still be much faster than random access to a disk file.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: brettc431 on April 25, 2013, 11:01:27 AM
Memory is not an issue for our project, according to the instructor, I just need to make sure I get a working command tail so I can start testing.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: MichaelW on April 25, 2013, 02:46:20 PM
I think most applications ignore the command tail length in the byte at 80h and just scan for the trailing CR. The attachment contains a demo that manipulates the command tail and does a dump of the entire PSP. Since most DOS functions that take null-terminated string arguments expect the strings to be in the default data segment, the demo copies the command tail from the PSP to the default data segment.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: dedndave on April 25, 2013, 04:35:46 PM
you're probably right, Michael
although, i remember writing some parsing loops that used the count
i also used LODSB and LOOP, so don't let Hutch see this post - lol
;DS = PSP segment

        mov     si,80h        ;PSPTailLen
        lodsb                 ;SI now points to the tail
        cbw
        xchg    ax,cx

loop00: lodsb
;
;parsing code
;
        loop    loop00
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: FORTRANS on April 25, 2013, 09:57:35 PM
Hi Dave,

   In my code I have a check for a command tail.  The ES segment
register points to the PSP on program load.  And the carriage
return that terminates the command line is not part of the count.

        MOV     BL,ES:[80H]     ; Length of cmd tail
        XOR     BH,BH           ; Length byte -> word
        XOR     CX,CX           ; Zero tail length
        CMP     BL,1            ; must be non-zero
        JB      FN2_3


   Just a quick and easy sanity check.

Hi Michael,

   If you want to allocate memory, you can skip the deallocation
steps if you use a linker option to limit the memory allocated to
the program when it is loaded.  Oh, that seems very version
dependent.  Just checked to see the spelling, and some versions
don't support it.  Anyway, if supported, the /CPARMAXALLOC or /CP:
option will limit the memory allocated to a program.  /CP:1 will
let the linker limit the program's memory to only what it needs
to load properly.  Then you can allocate memory as you mentioned.
Just a short cut.

Regards,

Steve N.
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: brettc431 on April 25, 2013, 10:57:36 PM
This is my final code before we have to test it today and show our instructor that it works.  I don't have matlab on my laptop so I'm going to post it up here for anyone to look at if they want.  Just want to know if there are any errors I haven't corrected before we get into the lab today.  Thanks again for all your help everyone.


.MODEL SMALL ;Defines memory model as small which uses separate segments for code and data
.386 ;Microprocessor number
.STACK ;Stack segment defined as 1024 by default
.DATA ;Begins definition of the data type used in this project

mrc DD ?
scale DD ?
D DD ?
row DB ?
col DB ?
e DD ?
ep1 DD ?
M DD 10000 DUP(?)
INPUT DB "input", 0
OUTPUT DB "output", 0
IHANDLE DW ?
OHANDLE DW ?



;-------------------------------------------------------------------------------------
;calcoffset takes two input variables and calculates the equation: (op2-1)*op1+(op1-1)
;The value is returned into M[EAX]
;-------------------------------------------------------------------------------------
calcoffset MACRO op1, op2 
PUSH ESI
PUSH EDI
MOV ESI, op1
MOV EDI, op2
DEC EDI
MUL EDI
ADD EAX, ESI
DEC EAX ;M[EAX]
POP EDI
POP ESI
ENDM
;------------------------------------------------------------------------------------

.CODE
MAIN PROC FAR
.STARTUP
;Program:

PUSHAD
MOV EAX, 0h
MOV AH, 62h
INT 21H
MOV ES, BX

MOV SI, 81h
CMP BYTE PTR ES: [SI-1], 1
JBE NO_TAIL

MOVZX ECX, BYTE PTR ES:[SI-1]
L0: MOV DL, ES:[SI]
INT 21H
INC SI
LOOP L0

NO_TAIL: MOV DL, 0Ah
INT 21H
MOV DL, 0Dh
INT 21H



MOV BP, 0
MOV SI, 0

MOV AX, 3D00h ;Open input file
MOV DX, OFFSET INPUT
INT 21H
MOV IHANDLE, AX

MOV AX, 3D01h ;Open output file
MOV DX, OFFSET OUTPUT
INT 21H
MOV OHANDLE, AX

MOV BX, IHANDLE
MOV CX,2    ;Want to read two bytes.
MOV DX, OFFSET D
MOV AH, 3FH ;Read
INT 21H
JC  QUIT
    CMP AX,2
       
       
        MOV CX,8    ;Want to read eight bytes.
MOV DX, OFFSET M
MOV AH, 3FH ;Read
INT 21H
JC  QUIT
    CMP AX, 8
JNE QUIT

MOV ESI, 1
MOV EDI, 1
MOVZX EAX, row



MOV ECX, ESI
MOV EBP, 1
DEC ECX
L1:
calcoffset EBP, EBP
MOV EDX, M[EAX]
MOV e, EDX
INC ESI
MOV ESI, EBP
MOV EDI, EBP
calcoffset ESI, EBP
MOV EDX, M[EAX]
MOV ep1, EDX

;calc scale to fpu
FINIT
FLD e
FLD ep1
FDIV
FST scale
JMP L2

RETURN: JMP L1

L2:
calcoffset ESI, EDI
MOV EDX, M[EAX]
MOV mrc, EDX

;fpu to calc mrc*scale+e
FINIT
FLD mrc
FLD scale
FMUL
FCHS
FLD e
FADD
FST mrc

INC EDI
MOVZX EDX, col
CMP EDI, EDX
JBE L2
INC ESI
MOVZX EDX, row
CMP ESI, EDX
JBE L2
JMP RETURN

     
        MOV AH, 40h
MOV BX, OHANDLE
MOV CX, LENGTHOF M
MOV DX, OFFSET OUTPUT
INT 21H


MOV AH, 3Eh
MOV BX, IHANDLE
INT 21H
        MOV BX, OHANDLE
        INT 21H
       
       
QUIT:  .EXIT
MAIN    ENDP
      END
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: dedndave on April 25, 2013, 10:59:52 PM
right - as i said before, the DS and ES registers point to the PSP at start-up
so, before i set the DS register, i would set the ES register to the local data segment
DS is still pointing to the PSP
so LODSB gets a byte from the command line tail and STOSB stores it in the data segment "parsed buffer"
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: dedndave on April 25, 2013, 11:01:35 PM
Brett...

at the end of the program source....
        END     MAIN

the END directive should reference the entry point
Title: Re: Reduced Row-Echelon Form of a Matrix Help
Post by: brettc431 on April 25, 2013, 11:11:47 PM
I always miss little obvious things when it comes to code, thanks  :t