Product of nasm matrices

1

I have to make an algorithm that multiplies an array A by an array B and places the result in a third array. The arrays are square, of the same size and will be passed by reference by another C program.

The problem is that the errors only appear when I try to compile the .c, while the .asm is linked without problems and I have no idea where I'm going wrong. If anyone can give a light, I am grateful.

;mulMatriz_asm(int mA[][MATRIZ_SIZE], int mB[][MATRIZ_SIZE], int mRes[][MATRIZ_SIZE], int mSize)
    SECTION .text

    global mulMatriz_asm

mulMatriz_asm:
    incr equ 4

    %define offma 0     ;deslocamento mA
    %define offmb 0     ;deslocamento mB
    %define offmres 0   ;deslocamento mRes

    push ebp
    mov ebp, esp
    mov ebx, [ebp+20]

    sub eax, eax
    sub ecx, ecx
    sub edx, edx

colRes:;edx -> k 
    push eax
    push ecx
    push edx
    push ebx

    mov eax, [ebp+8];*mA
    mov eax, [eax+offma];ma[i][j]

    mov ecx, [ebp+12];*mB
    mov ecx, [ecx+offmb];mb[j][k]
    mul ecx

    mov edx, [ebp+16];*mRes
    mov ebx, [edx+offmres];mRes[i][k]
    add ebx, eax

    mov [edx+offmres], ebx;mRes += mA * mB

    mov eax, incr

    mov ebx, offmb
    add ebx, eax        ;próxima coluna de mB
    %define offmb ebx

    mov ecx, offmres
    add ecx, eax        ;próxima coluna de mRes
    %define offmres ecx

    pop ebx
    pop edx
    pop ecx
    pop eax

    inc edx
    cmp edx, ebx
    jl colRes
colA:;ecx -> j
    sub edx, edx

    push edx
    push ecx

    mov edx, incr

    mov ecx, offma
    add ecx, edx    ;próxima coluna de mA
    %define offma ecx

    mov edx, offmb
    add edx, ebx    ;próxima linha de mB
    %define offmb edx

    pop ecx
    pop edx

    inc ecx
    cmp ecx, ebx
    jl colRes
linhaA:;eax -> i
    sub ecx, ecx
    sub edx, edx

    push ecx

    mov ecx, offma
    add ecx, ebx    ;proxima linha de mA
    %define offma ecx

    mov ecx, offmres
    add ecx, ebx    ;proxima linha de mRes
    %define offmres ecx

    pop ecx

    inc eax
    cmp eax, ebx
    jl colA

    ret
    
asked by anonymous 06.06.2016 / 21:53

1 answer

0

Following the top issues in your code:

  • The stack frame created, is not restored before return. At the end of the function, it is necessary to restore the stack:

    ...
    mov     esp, ebp
    pop     ebp
    ret
    
  • The command %define defines a macro and is not a statement in assembly . For example, at line %define offmres ecx , the value of the offmres macro will not be updated with the value stored in register ecx (and this will cause problems in calculating the offset array) p>

  • Since the prototype of the function in C indicates that the data type of the array is int (integer with sign), the ideal is to use the imul to multiply (instead of mul )

Below is a commented and didactic example (not optimized) to multiply matrices with nasm . You can use it as a starting point to fine-tune your algorithm.

This algorithm uses local variables, allocated in the stack, to store the indexes of loopings ( i , j and k ) and the scalar product ( sum ): / p>

; mulMatriz_asm(
;   int mA[][MATRIZ_SIZE], 
;   int mB[][MATRIZ_SIZE], 
;   int mRes[][MATRIZ_SIZE], 
;   int mSize)

section .text

global _mulMatriz_asm

; --- Macros ---
; Parametros
%define mA              dword [ebp + 8]     ; matriz A
%define mB              dword [ebp + 12]    ; matriz B
%define mC              dword [ebp + 16]    ; matriz Resultado
%define mSize           dword [ebp + 20]    ; tamanho

; Variaveis locais
%define sum             dword [ebp - 4]     ; utilizada no cálculo do produto escalar
%define indice_i        dword [ebp - 8]     ; utilizado no "for (i=0..."
%define indice_j        dword [ebp - 12]    ; utilizado no "for (j=0..."
%define indice_k        dword [ebp - 16]    ; utilizado no "for (k=0..."

; --- Início ---
_mulMatriz_asm:
    push    ebp                 ; Inicializa o frame
    mov     ebp, esp
    sub     esp, $80            ; Aloca espaço para as variáveis locais...
    push    ebx                 ; ...e salva os registradores
    push    ecx
    push    edx
    push    esi
    push    edi

    mov     esi, mA             ; armazena o endereço base de mA no registrador esi
    mov     edi, mB             ; armazena o endereço base de mB no registrador edi
    mov     indice_i, $0        ; inicializa o looping "i" com zero

forI:
    mov     ecx, indice_i
    cmp     ecx, mSize          ; se (i >= mSize) então vai para "fim"
    jge     fim                             

    mov     indice_j, $0        ; inicializa o looping "j" com zero
forJ:
    mov     ecx, indice_j
    cmp     ecx, mSize          ; se (j >= mSize) então vai para "fimForI"
    jge     fimForI

    mov     sum, $0             ; inicializa a somatória do produto escalar

    mov     indice_k, $0        ; inicializa o looping "k" com zero
forK:
    mov     ecx, indice_k
    cmp     ecx, mSize          ; se (k >= mSize) então vai para "fimForJ"
    jge     fimForJ 

    mov     ebx, indice_i       ; calcula o endereço do elemento mA[i][k]
    imul    ebx, mSize                      
    add     ebx, indice_k       ; ebx = (indice_i * mSize + indice_k) 
    shl     ebx, 2              ; multiplica ebx por 4 ==> sizeof(int) para 32bits
    mov     eax, [esi + ebx]    ; carrega o elemento da matriz A em eax

    mov     ebx, indice_k       ; calcula o endereço do elemento mB[k][j] 
    imul    ebx, mSize
    add     ebx, indice_j
    shl     ebx, 2              ; ebx = (indice_k * mSize + indice_j) * 4 
    mov     ecx, [edi + ebx]    ; carrega o elemento da matriz B em ecx

    imul    eax, ecx            ; eax <- mA[i][k] * mB[k][j]
    add     sum, eax            ; acumula o resultado na variável local sum

fimForK:
    inc     indice_k            ; incrementa o looping "k"
    jmp     forK

fimForJ:
    mov     ebx, indice_i       ; calcula o endereço do elemento mRes[i][j]
    imul    ebx, mSize
    add     ebx, indice_j
    shl     ebx, 2              ; ebx = (indice_i * mSize + indice_j) * 4 
    mov     eax, sum            ; carrega a somatória em eax
    mov     ecx, mC             ; carrega o endereço base de mRes em ecx
    mov     [ecx + ebx], eax    ; armazena o resultado da somatória em mRes[i][j]

    inc     indice_j            ; incrementa o looping "j"
    jmp     forJ    

fimForI:
    inc     indice_i            ; incrementa o looping "i"
    jmp     forI    

fim:
    pop     edi                 ; restaura os registradores salvos
    pop     esi
    pop     edx
    pop     ecx
    pop     ebx
    mov     esp, ebp            ; restaura o frame
    pop     ebp
    ret                         ; retorna

tested with NASM version 2.12.02 compiled on Jul 6 2016

    
23.10.2016 / 18:52