# masm32 programming problem with matrix



## ericlzk (Nov 7, 2007)

I am having trouble understanding how the LEA instruction works on a 4x4 matrix and have try searching the net for some answers. This is my program below.
I am trying to add the 3rd row and output it on the screen. Please help 
I have try to only output one of numbers to the screen but not successful

;ex5b.asm

include c:\MASM32\work\headings2.inc
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data

xyz Dword 1, 3, -3, 7 ; A 4X4 MATRIX TABLE
Dword 2, -5, 3, 0 
Dword 1, 7, -2, 8 ;17-28
Dword -1, 5, 0, 6

.code
start: ; The CODE entry point to the program

mov ecx,3 ; row
mov edx,1 ; column

abc: lea esi,[xyz-4 + ecx*4+ edx]
mov eax,esi
mov [xyz],eax
; inc edx
; cmp edx,4
; jna abc
invoke StdOut, addr [xyz]

exit


----------



## johnhe (May 11, 2007)

It looks like you are confused about the layout of the memory used to hold the matrix and the offset of the start of the matrix rows. In assembly like in C and C++ you need to understand that arrays and matrixes are zero based but you are assuming the column is 1 based (mov edx,1 ;column). It also looks like you are assuming that each row contains 4 bytes (ecx*4) when in fact they contain 16 bytes (4 dwords).

You also seem confused about how to move the value from the matrix into a register. The 2 instructions mov eax, si and then mov [zyz],eax copy the address of the current matrix element into xyz[0][0] overwriting the existing value with an address.

Here is an example of how to add all of the values in the 3rd row of the matrix to get a total.

.data

xyz Dword 1, 3, -3, 7 ; A 4X4 MATRIX TABLE
Dword 2, -5, 3, 0 
Dword 1, 7, -2, 8 
Dword -1, 5, 0, 6

total Dword 0

.code

mov ecx,2 * 16 ; offset of 3rd row
mov edx,0 ; column

abc:
; Calc adress of next element in matrix in esi
lea esi,[xyz + ecx + edx * 4]

; Copy value from this element in matrix into eax
mov eax, [esi]

; Add current matrix value to the total
add total,eax

; Increment the counter
inc edx

; Have we passed the last column
cmp edx, 4

; Keep looping if edx is less than 4
jnae abc

; When we get here the value in the variable total should be 14 decimal.

I hope this helps,
John Hensley
www.resqware.com


----------



## ericlzk (Nov 7, 2007)

Thanks alot,.. I will study it further... Please let me know how can I display it on the sceen the correct value. I am getting a melody sign


----------



## johnhe (May 11, 2007)

It sounds like you might be passing the wrong type of value on the stack to the StdOut function but I can't tell because I don't any way to know what StdOut does. If you post the contents of the c:\MASM32\work\headings2.inc file that your code includes I'll take a look at the StdOut function and see if I can tell you what you need to pass to it.

John Hensley
www.resqware.com


----------



## ericlzk (Nov 7, 2007)

The file headings2.inc. The contents of the file is as below for this file.

.486 ; create 32 bit code
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive

include \masm32\include\windows.inc ; always first
include \masm32\macros\macros.asm ; MASM support macros

; -----------------------------------------------------------------
; include files that have MASM format prototypes for function calls
; -----------------------------------------------------------------
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc

; ------------------------------------------------
; Library files that have definitions for function
; exports and tested reliable prebuilt code.
; ------------------------------------------------
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib

; --------------------------------------------------------------
; This is a prototype for a procedure used in the demo. It tells
; MASM how many parameters are passed to the procedure and how
; big they are. This makes procedure calls far more reliable as
; MASM will not allow different sizes or different numbers of
; parameters to be passed. Note that a C calling convention
; procedure CAN have a variable number of arguments but these
; examples use the normal Windows STDCALL convention which is
; different.
; --------------------------------------------------------------

This is a conflict between the old software my uni was using, so I had to make two files of the headings.inc

So how I can I display the answer to the screen. I use invoke StdOut, addr [ Total] 
function and it gives me a character display.


----------



## ericlzk (Nov 7, 2007)

i finally found out how to display the thing , it is using the print command as below this program. Now I need to add the 4th column together and I also need to know how to add the minor diagonal for the matrix -1,7,3,7 . i am still confuse of the row and column??

;ex5b.asm
include c:\MASM32\work\headings2.inc

.data
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

xyz Dword 1, 3, -3, 7 ; A 4X4 MATRIX TABLE
Dword 2, -5, 3, 0 
Dword 1, 7, -2, 8
Dword -1, 5, 0, 6

total Dword 0
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; This add the 4th column
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

.code
start: 
mov ecx,0 ; first row
mov edx,3 ; 4th column

abc:
lea esi,[xyz + ecx*4 + edx] ; Calc adress of next element in matrix in esi 
mov eax, [esi] ; Copy value from this element in matrix into eax
add total,eax ; Add current matrix value to the total
INC ECX
INC ECX
INC ECX
INC ECX ; Increment the counter move to next column 
cmp ecx,12
jnae abc
print " The Answer is "
print str$(total)," ",13,10

exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end start


----------



## johnhe (May 11, 2007)

This example shows how to access and print out each individual element in the matrix. To access a matrix member you need to calculate the byte offset of the element and add this to matrix location in memory. This is what the lea esi,[...] instruction allows you to do. For example to access the individual element Matrix[3][2] you would use the forumla (Matrix address + (bytes per row * 3) + (Bytes per dword * 2)). The operand to the lea instruction in the sample is:

lea esi,[MyMatrix + eax + edx * 4]

Where eax contains (row index * BYTES_IN_ROW) and edx contains the column index effectively creating this psudeo instruction:

lea esi,[address of MyMatrix + byte offset of row + (column * bytes in a dword)]

.486 ; create 32 bit code
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive

include \masm32\include\windows.inc ; always first
include \masm32\macros\macros.asm ; MASM support macros

; -----------------------------------------------------------------
; include files that have MASM format prototypes for function calls
; -----------------------------------------------------------------
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc

; ------------------------------------------------
; Library files that have definitions for function
; exports and tested reliable prebuilt code.
; ------------------------------------------------
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib

MAX_ROW EQU 4 ; Number of rows in the matrix
MAX_COL EQU 4 ; Number of columns in the matrix
BYTES_IN_ROW EQU 4 * 4 ; 4 elements times number bytes in a dword

.data

MyMatrix Dword 1, 3, -3, 7 ; A 4X4 MATRIX TABLE
Dword 2, -5, 3, 0 
Dword 1, 7, -2, 8 ;17-28
Dword -1, 5, 0, 6

FormatString db 'MyMatrix[%d][%d]=%d',0dh,0ah,0
szBuffer db 256 dup(?)

.code

public start
start:

mov ecx,0 ; Index of first row

PrintRow:
mov edx,0 ; Index of first col

PrintCol:
mov eax, BYTES_IN_ROW
mul cl ; eax = byte offset of this row in matrix
lea esi,[MyMatrix + eax + edx * 4]
mov eax,[esi]
pusha
invoke wsprintf, addr szBuffer, addr FormatString, ecx, edx, eax
invoke StdOut, addr szBuffer
popa
inc edx ; Get index of next 
cmp edx,4 ; Have we passed the last column
jnae PrintCol ; Keep looping until all columns done in this row

inc ecx ; Get index to next matrix row
cmp ecx, MAX_ROW
jnae PrintRow ; Keep looping until all rows are done

exit
end start


----------



## ericlzk (Nov 7, 2007)

Thanks a lot man.. But I am confuse that u said that dword is 16 bytes when I search the internet it is saying that a dword is a 32 bit and which means 4bytes .. as a byte have 8bits ? ? ? ? . However your example program gave me an edge on how to proceed the next one on by own. thanks man..:up: Do you know if it is possible to split a BCD into a 4 bit when there is a two digit inside like this....

abc db 00100010b ( in binary)

basically I need to split the above array into 0010 and 0010 and add 30h to each to display it separately on the screen '22' I can display it correctly '22 on the screen if I define the array like this 00000010b,00000010b easily. I just want to know if this is possible as most books describe packed BCD but never explain how to unpacked a bcd

Regards,,
Eric


----------



## johnhe (May 11, 2007)

I didn't mean to imply that a dword is 16 bytes. A dword is 32 bits or 4 bytes. A row in the matrix consists of 4 dwords which makes the row 16 bytes long. Since addressing in assembly is always done in byte offsets it means that to locate the start of a row in the matrix one needs to multiply the zero based row number by 16 (4 bytes per dword times 4 dwords per row).

I don't really understand what you are trying do with the BCD stored values but unless you are only dealing with unsigned numbers there would be a lot more more than simply adding 30h to each 4 bit value because you would need to handle negative numbers.

If you only want to access the 4 bit BCD values you can load the data from the array into a register and then shift right by 4,8,12, etc. to move the desired 4 bits into the least significant position and then mask them off by anding with 0fh.

mov eax,[esi]
shr eax, 24
and eax, 0fh
add eax, 30h

Regards,
John


----------



## ericlzk (Nov 7, 2007)

Dear John,

Thanks for the input, I get what u mean about the help you gave... I manage to extract 4 bits of the 8bit by the and operation and mov the 4 bit data into another buffer one by one and display it. I have another problem. First this is a macro which is given on the top plus my program.

The question is I was ask to write a program that ask user to enter two numbers decimal numbers(8 digits maximum; means 4 digits each) using the StdIn function and shows their sum on the screen.

Basically my lecture just gave me this 
Enter Number1 
8888 
Enter Number2
1111
The Sum is 
9999

how do I limit the digit and do addition and display it correctly. Do I use the function AAA?

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
MakeToString macro lpstring ;Replaces CR (13) with 0
local look,replace
mov esi,0

look: mov al,[lpstring+esi] ;get character
cmp al,0dh ;is it CR?
je replace ;if so go and replace it 
inc esi ;otherwise continue looking
jmp look
replace:
mov [lpstring+esi],00 ;Replace CR with 0
endm
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data?

abc db 5 Dup(?)
cde db 5 Dup(?)

.code

start: 
print "Enter Number 1:",13,10
invoke StdIn, addr [abc],4
mov eax,[abc]
MakeToString eax
print "Enter Number 2:",13,10
invoke StdIn, addr [cde],1
MakeToString cde
invoke StdOut, addr [abc]

exit

; « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « «

end start


----------



## johnhe (May 11, 2007)

The easiest way to do this would be to read, validate and process 1 digit at time rather than trying to process a string. I would suggest using an algorithm such as this to avoid the need for error checking and packing/unpacking BCD numbers. This should be very straightforward to implement with masm32.

// Prompt for first number
DWORD Num1 = 0;
while ( (c = getchar()) != 13 && Num1 < (MAX_DWORD/10) )
{
if ( c >= '0' && c <= '9' )
{
DWORD Digit = c -'0';
Num1 *= 10;
Num1 += Digit;
}
}

// Prompt for second number
DWORD Num2 = 0;
while ( (c = getchr()) != 13 && Num2 < (MAX_DWORD/10) )
{
if ( c >= '0' && c <= '9' )
{
DWORD Digit = c - '0';
Num2 *= 10;
Num2 += Digit;
}
}

DWORD Total = Num1 + Num2
Output Total


----------



## ericlzk (Nov 7, 2007)

is this the same as masm32... I could not put this in masm32 to run it.


----------



## johnhe (May 11, 2007)

No, it is pseudo code just to give you an example of the algorithm. I was trying to give you an idea of how to generate a binary number from user input. Here is some masm32 code that shows how to get generate a binary number from keyboard input. It's basically an implementation of the first while loop from the pseudo code above.

.486 ; create 32 bit code
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive

include \masm32\include\windows.inc ; always first
include \masm32\macros\macros.asm ; MASM support macros

; -----------------------------------------------------------------
; include files that have MASM format prototypes for function calls
; -----------------------------------------------------------------
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\msvcrt.inc


; ------------------------------------------------
; Library files that have definitions for function
; exports and tested reliable prebuilt code.
; ------------------------------------------------
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\msvcrt.lib

.data

RequestFirstNumber db 'Enter the first 4 digit number',0dh,0ah,0
RequestSecondNumber db 'Enter the second 4 digit number',0dh,0ah,0
CrLf db 0dh,0ah,0

Number Dword 0
Digit DWORD 0

.code

public start
start:

; Prompt user for first number
invoke StdOut, addr RequestFirstNumber


; Number of digits to get in loop
mov ecx,4

Get4Digits: ; Start of loop to get 4 digits

; Get next character from keyboard
pusha
invoke crt__getch 
mov Digit, eax
popa

; Check for enter key to end input
cmp Digit, 13 
je HaveNumber

; Only allow valid digits
cmp Digit, 30h 
jb Get4Digits
cmp Digit, 39h
ja Get4Digits

; Display the valid digit
pusha 
push Digit
invoke crt_putchar
add esp,4
popa

; Convert digit to binary
sub Digit,30h 

mov eax,Number
mov edx, 10
mul edx
add eax, Digit
mov Number,eax
loop Get4Digits

HaveNumber:

invoke StdOut, addr CrLf
invoke StdOut, addr RequestSecondNumber

exit
end start


----------

