NASM中的矩阵表示

时间:2013-05-17 09:10:05

标签: assembly x86 nasm

我正在尝试编写一个使用NASM实现矩阵的程序。作为初学者,我尝试在NASM中重写以下C代码。 C代码:

    for(i = 0 ; i< 3; i++){
        for(j = 0 ;j < 3; j++)
            a[i][j] = 0 ;
    }

我的以下NASM代码实现是:

    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

但是我发现我的程序在一个无限循环中失败了,最值得注意的是edx的值没有递增。作为初学者,我很少怀疑我是否应该以这种方式实现矩阵。

我正在寻找导师的建议。我使用的是UBUNTU 11.04操作系统。

我的问题更新:

遵循导师Brendon的建议,我按照以下方式更改了上述代码;仍然没有得到我想要的输出:

   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; I am using Row major represntation
       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,4
        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

我的预期输出将是

    0 0 0
    0 0 0
    0 0 0

但输出来的是 0123012301230 0 0 分段错误

我仍然在寻找你的建议。 谢谢。

1 个答案:

答案 0 :(得分:1)

您没有展示如何在C中定义“数组数组”;但是从使用a[r][c]开始,我假设你正在做类似的事情:

int a[4][4];

在内存中,这将是一个包含16个整数的数组(或4个4个整数组)。在您的NASM代码中,您可以执行以下操作:

section .bss
arr1 resd 4
arr2 resd 4

这不是16个整数的数组。它是4个4个整数的独立数组。它应该是:

section .bss
arr resd 4*4

MUL指令将EAX中的32位值乘以另一个32位值(在您的情况下为4),并将64位结果存储在EDX:EAX中。您正在使用EDX来控制内循环,MUL正在破坏EDX。这是你的无限循环的原因(基本上,它正在循环,直到0 * 4的结果不小于0x0000000400000000)。

另请注意,乘法是不必要的。将“sizeof(int)”添加到指针更容易。例如(使用C作为伪代码)for(void *c = a; c < (void *)a + 4 * sizeof(int); c += sizeof(int)) { ... }。在汇编中,这可能看起来像:

    mov edx,arr
.next:

    ...

    add edx,4
    cmp edx,arr+4*4
    jb .next

同样适用于外循环。例如(合并):

    mov ecx,arr
.next1:

    mov edx,ecx
    lea edi,[ecx+4*4]
.next2:

    ...

    add edx,4
    cmp edx,edi
    jb .next2

    add ecx,4*4
    cmp ecx,arr+4*4*4
    jb .next1

当然也不需要嵌套循环,因为你对数组数组中的每个整数做了同样的事情。你可以这样做:

    mov ecx,arr
.next1:

    mov dword [ecx],0

    add ecx,4
    cmp ecx,arr+4*4*4
    jb .next1

这可以再次简化 - 它可能只是C中的memset();或者像汇编这样的东西:

    mov edi,arr     ;es:edi = address of array of arrays
    mov ecx,4*4     ;ecx = size of array of arrays (16 integers)
    xor eax,eax     ;eax = value to fill the integers with
    rep stosd       ;Fill the array