NASM - The Netwide Assembler
NASM Forum => Using NASM => Topic started by: Frasier on March 07, 2011, 08:06:03 PM
-
Hi,
I have to print a matrix in assembly and the matrix is defined as follows
matrixA DQ 2 ; ROWS
DQ 3 ; COLS
DQ 1, 2, 3 ; 1st row
DQ 4, 5, 6 ; 2nd row
My problem is that I don't know how to reach the ROWS and COLS values in the print_matrix loop. This is what I have done so far(Note that, in the for loops, instead of the value 2 I should have put the number of rows and columns of the matrix)
egment .text
global _start
_start:
main:
mov rax, matrixA ; matrixA.print ()
push rax
call matrix_print
add rsp, 8
mov rax, matrixB ; matrixB.print ()
push rax
call matrix_print
add rsp, 8
; ---------------------------------------------------------------------
matrix_print: ; void matrix_print ()
push rbp ; setup base pointer
mov rbp, rsp
call output_newline ; output.newline()
; for(row=0; row < this.ROWS; row++)
mov rax, 0 ; row=0
nextr: cmp rax, 2 ; row < this.ROWS
jge endr ;
; for(col=0; col < this.COLS; cols++)
mov rbx, 0 ; col=0
nextc: cmp rbx, 2 ; col < this.COLS
jge endc ; if col>=2 go to endc
call output_tab ; output.tab ()
call output_int ; output.int (this.elem[row, col])
inc rbx ; col ++
jmp nextc
endc: inc rax ; row ++
call output_newline
jmp nextr
endr:
pop rbp ; restore base pointer & return
ret
; --------------------------------------------------------------------------
segment .data
; Declare test matrices
matrixA DQ 2 ; ROWS
DQ 3 ; COLS
DQ 1, 2, 3 ; 1st row
DQ 4, 5, 6 ; 2nd row
matrixB DQ 3 ; ROWS
DQ 2 ; COLS
DQ 1, 2 ; 1st row
DQ 3, 4 ; 2nd row
DQ 5, 6 ; 3rd row
matrixC DQ 2 ; ROWS
DQ 2 ; COLS
DQ 0, 0 ; space for ROWS*COLS ints
DQ 0, 0 ; (for filling in with matrixA*matrixB)
-
mov rax, matrixA ; <-- get the address of matrixA
push rax ; <-- this saves the matrix address on the stack
call matrix_print ; <-- call your print function
add rsp, 8 ; <-- restore the stack
Here you've already supplied the address of the label matrixA on the stack to the matrix_print() call.
I've added comments to your code to help.
You now need to simply use the address reference from inside matrix_print:
mov rbx, [rbp+8] ; get the address passed to the function and store in rbx
mov rax, [rbx] ; get the number of rows
mov rcx, [rbx+4] ; get the number of columns
add rbx, 8 ; rbx now points to your first matrix value
.
. ; process your array
.
That should be enough to get you going. Just remember that rax,rcx,rdx, r8, and r9 are considered volatile and will get trashed when you call any operating system function. You will need to save those registers you use prior to making any system calls if you need their values to persist...
-
mov rbx, [rbp+8] ; get the address passed to the function and store in rbx
mov rax, [rbx] ; get the number of rows
mov rcx, [rbx+4] ; get the number of columns
Wouldn't the address be at [rbp + 16], and columns at [rbx + 8] in 64-bit code? I've never done 64-bit code, so I'm just guessing...
Best,
Frank
-
Frank is correct. I should know better than post "idea" code first thing in the morning :P
The correct code sequence should be:
mov rbx, [rbp+16] ; get the address passed to the function and store in rbx
mov rax, [rbx] ; get the number of rows
mov rcx, [rbx+8] ; get the number of columns
add rbx, 16 ; rbx now points to your first matrix value
.
. ; process your array
.
64-bit programming is no more difficult than 32-bit programming.
Using one register for an "unsigned long" rather then edx:eax is sweet and the extra registers are a godsend. ;)
Program size is increased slightly due to the prefixes and you can take hits in speed if not careful ( think alignment ).
However with a 64-bit OS you can finally make use of RAM in excess of 4GB. Having multiple graphic apps running concurrently without swapping is heavenly. I use a Win7 64-bit host with Fedora 14 running Gnome in a VirtualBox VM along with my developer IDE's loaded for both environments, plus web-browsers, email app, and Lord of the Rings online when I'm getting my game on! ;D