Author Topic: Accessing DQ segment and registers  (Read 8039 times)

Offline Frasier

  • Jr. Member
  • *
  • Posts: 2
Accessing DQ segment and registers
« on: March 07, 2011, 08:06:03 PM »
Hi,

I have to print a matrix in assembly and the matrix is defined as follows
Code: [Select]
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)
Code: [Select]
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)
« Last Edit: March 07, 2011, 08:12:09 PM by Frasier »

Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 429
  • Country: us
Re: Accessing DQ segment and registers
« Reply #1 on: March 08, 2011, 12:25:57 PM »
Code: [Select]
    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:

Code: [Select]
    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...


Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Accessing DQ segment and registers
« Reply #2 on: March 08, 2011, 10:22:58 PM »
Code: [Select]
    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


Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 429
  • Country: us
Re: Accessing DQ segment and registers
« Reply #3 on: March 08, 2011, 11:38:48 PM »

Frank is correct.  I should know better than post "idea" code first thing in the morning :P

The correct code sequence should be:

Code: [Select]
    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