0

我正在尝试使用 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 Segmentation fault

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

4

1 回答 1

1

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

int a[4][4];

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

section .bss
arr1 resd 4
arr2 resd 4

这不是 16 个整数的数组。它是 2 个由 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

这可以再次简化 - 它可能只是memset()在 C 中;或组装中的类似内容:

    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
于 2013-05-17T12:19:53.267 回答