NASM - The Netwide Assembler

NASM Forum => Programming with NASM => Topic started by: saugata bose on May 17, 2013, 09:20:28 AM

Title: Matrix representation in NASM
Post by: saugata bose on May 17, 2013, 09:20:28 AM
I am trying to write a program implementing matrix using NASM. As a beginner, I try to rewrite the following C code in NASM.
The C Code:
Code: [Select]
    for(i = 0 ; i < 3; i++){
        for(j = 0 ; j < 3; j++)
            a[i][j] = 0 ;
    }
My following implementation of NASM code is:
Code: [Select]
section .data
          msg db "%d"
          four dd 4
          spce db " ",0
          nl db 10
    section .bss
          arr1 resd 4
          arr2 resd 4
    section .text
          global main
          extern printf
    main:
          nop   
          xor ecx,ecx
          xor eax,eax
          xor ebx,ebx
   lp1:                                 ;to implement "for(r = 0 ; r < 4; r++)"
          mov ebx, arr1
          mov eax,ecx
          mul dword[four]   
          add ebx,eax   
          cmp ecx,4
          jl entryOflp2
          jmp done
   entryOflp2:                           ; to implement for(c = 0 ; c < 4; c++)
          push ebx
          push ecx
          xor ebx,ebx
          xor edx,edx
   lp2:
          mov ebx, arr2
          mov eax,edx   
          mul dword[four]
          add ebx,eax

          mov dword[ebx],0              ; to initial a[r][c]=0
          inc edx
          cmp edx,4
          jl lp2
   endOflp2:
          pop ecx
          pop ebx
         
          inc ecx
          cmp ecx,4
          jl lp1
    done:
              ret
But I found that my program is failed in a inifinite loop and most notably value of edx is not incrementing. As a beginner, I have few doubts that whether I should implemet a matrix in this way or not.

I am looking for advice from the mentors. I am using UBUNTU 11.04 OS. THANK YOU.


Title: Re: Matrix representation in NASM
Post by: Frank Kotler on May 17, 2013, 01:33:39 PM
Hi Saugata,

Well... first thing: edx is not incrementing. The "mul" instruction (and imul and div and idiv) are tricky because the operands are implied. "mul", by a dword, multiplies eax by your dword and puts the result in edx:eax - that is, edx * 4G + eax. It multiplies a 32-bit number by a 32-bit number and gives a 64-bit result. Since your numbers are small, the result fits into eax and the "high part" in edx is set to zero every time you do "mul"! Using some other register but edx (esi and edi are unused) for your inner-loop counter would solve this.

You define your "matrix" like:
Code: [Select]
    section .bss
          arr1 resd 4
          arr2 resd 4
Two "rows"(?) of four dwords each. You're trying to initialize four rows of four dwords each! Since there isn't anything after "arr2", this buffer overflow probably isn't going to cause an immediate problem, but it's still a buffer overflow, and we ought to avoid 'em! (besides introducing bugs, this allows "exploits", and we know how much trouble those cause! Avoid!)

We want to "picture" our matrix being composed of "rows" and "columns", but in reality it's laid out in memory one byte after another (same as everything else on the computer). So we can calculate the address of say "row 2, column 3" as [matrix + row_number * width_of_row(* 4, for dwords) + column_number (* 4)]. Keep in mind that what we're probably calling the "first" row is really the "zeroth" row, for addressing purposes. (likewise columns, of course) This can be a particular problem in figuring out when we get to the "end". The last entry in a 4 by 4 matrix is "[matrix + 15 (*4, for dwords)]", not "[matrix + 16...]". You get that right, I think (except for only having two "rows" in your matrix).

You don't actually use "printf", but it looks like you're planning to. Keep in mind that calling "printf" will trash even more registers than "mul". :)

Give it another try, allowing room for all four rows and keeping in mind that "mul" trashes edx, and we'll talk more. You're on the right track!

Best,
Frank

Title: Re: Matrix representation in NASM
Post by: saugata bose on May 17, 2013, 02:28:01 PM
Dear Frank,
I am looking for Your help during all the the time after posting the query. Thanx mentor. I have changes my logic following your Row-Major matrix representation technique.. But I got NOW eerie results. For your conveniecnce I put my code here:
Code: [Select]
section .data
msg db "%d",0
four dd 4           ;word size
three dd 3         ;number of rows nd columns
spce db "   ",0
nl db 10
section .bss
arr1 resd 9
section .text
global main
extern printf
main:
nop
xor ecx,ecx
xor eax,eax
xor ebx,ebx
mov ebx, arr1
forI:
xor esi,esi
cmp ecx,3
jl forJ
jmp print
forJ:
cmp esi,3
jl initialization
inc ecx
jmp forI
initialization:                           ; it will give base address+4(number of colums*rowIndex+columIndex). 
                                             ;ecx=row index,esi=column index
mov eax,ecx
mul dword[three]
add eax,esi
mul dword[four]
add ebx,eax       
mov dword[ebx],0       ;set a[i][j]=0

inc esi
jmp forJ
print:
xor ecx,ecx
xor eax,eax
xor ebx,ebx
mov ebx, arr1
forI_2:
xor esi,esi
cmp ecx,3
jl forJ_2
jmp done
forJ_2:
cmp esi,3
jl print_task
pusha
push nl
call printf
add esp,3
popa
inc ecx
jmp forI_2
print_task:
mov eax,ecx
mul dword[three]
add eax,esi
mul dword[four]
add ebx,eax

pusha
push dword[ebx]
push msg
call printf
add esp,8
popa
pusha
push spce
call printf
add esp,4
popa

inc esi
jmp forJ_2
done:
nop

My intended output will be
  0 0 0
  0 0 0
  0 0 0
But the output comes here is
0123012301230 0 0
Segmentation fault

Still I am looking for your advice.

Thank You
Saugata
Title: Re: Matrix representation in NASM
Post by: Frank Kotler on May 17, 2013, 04:23:02 PM
Simple typo...
Code: [Select]
forJ_2:
cmp esi,3
jl print_task
pusha
push nl
call printf
add esp,3 ; <- should be 4, of course!
... that, and adding a "ret" at the end so we don't "fall off into the weeds", seems to give your expected output.

There's a "scaled index" addressing mode that might help you. Instead of:
Code: [Select]
mov eax,ecx
mul dword[three]
add eax,esi
mul dword[four]
add ebx,eax       
mov dword[ebx],0       ;set a[i][j]=0
You could do:
Code: [Select]
mov eax,ecx
mul dword[three]
add eax,esi
mov dword[ebx + eax * 4],0       ;set a[i][j]=0
Nothing wrong with the way you're doing it, but it's a handy addressing mode to know. The "scale" (multiplier) can be 1, 2, 4, or 8, useful for addressing arrays of bytes (you don't have to say "* 1", of course), words, dwords, or double-precision floats. (or qwords, in 64-bit code, I guess).

It was just the "add esp, 3" that was giving you the "weird" results.

I see you're getting good advice over at SO, too, so you should be able to close in on it!

Best,
Frank

Title: Re: Matrix representation in NASM
Post by: saugata bose on May 17, 2013, 04:37:59 PM
Dear Frank,

I dont say thank you. I feel grateful to have such a mentor for me whenever I feel I am at the brink of a hole. Thank you.


Saugata