Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 03.06.2013, 17:21   #1
munthrekosh
Пользователь
 
Аватар для munthrekosh
 
Регистрация: 12.11.2011
Сообщений: 80
Печаль Assembler под Windows (MASM32). Не работает процедура произведения матриц

Есть процедура. При её вызове ей сообщается:
  1. MAAd - адрес начала первой матрицы А
  2. MBad - адрес начала второй матрицы В
  3. MCad - адрес начала результирующей матрицы С
  4. RowA - количество строк в матрице А
  5. CalB - количество столбцов в матрице В
  6. СaRoAB - количество столбцов в матрице А или строк в В

Внутри регистрируются локальные переменные NeRA (i), NeCB (j) и NexCR (l), которые являются счетчиками для циклов.

Данная процедура должна совершать операцию произведения двух матриц и записывать результат в третью. Попутно заполняя некоторый буфер значениями ячеек результирующей матрицы, перемежаемыми запятыми.
Но данная процедура не работает, так как в буфере по завершению остается "0, ".

Подскажите, пожалуйста, где ошибка.


Код:
MatrProd proc MAAd: DWORD, MBAd: DWORD, MCAd: DWORD, 
             RowA: DWORD, CalB: DWORD, CaRoAB: DWORD 
 LOCAL NeRA: DWORD
 LOCAL NeCB: DWORD
 LOCAL NexCR: DWORD
 
 mov NeRA,0
 mov NeCB,0
 mov NexCR,0 
 .WHILE TRUE
   .WHILE TRUE; вычислить адрес и затем [],0
     ;---mov MCAd[NeRA*CalB+NeCB],0
     ;---МатрицаС[i,j]:=0
     ;---i=NeRA*CalB (номер строки на количество строк)
     ;---j=NeCB
  
     invoke IntMul, NeRA, CalB
     mov ebx, NeCB
     add eax, ebx
     mov ebx, DWORD PTR 4
     invoke IntMul, eax, ebx
     mov ebx, MCAd
     add eax, ebx
     mov [eax],DWORD PTR 0

     .WHILE TRUE
       ;mov eax, MBAd[NexCR*CalB+NeCB]
       invoke IntMul, NexCR, CalB
       mov ebx, NeCB
       add eax, ebx
       mov ebx, DWORD PTR 4
       invoke IntMul, eax, ebx
       mov ebx, MBAd
       add eax, ebx
       mov ebx, [eax]
       mov eax, ebx
   
       push eax
   
       ;mov ebx, MAAd[NeRA*CaRoAB+NexCR]
       invoke IntMul, NeRA, CaRoAB
       mov ebx, NexCR
       add eax, ebx
       mov ebx, DWORD PTR 4
       invoke IntMul, eax, ebx
       mov ebx, MAAd
       add eax, ebx
       mov ebx, [eax]
       
       pop eax
       invoke IntMul, eax, ebx
       push eax
   
       ;add MCAd[NeRA*CalB+NeCB],edx
       ;add MCAd[NeRA*CalB+NeCB],eax 
       invoke IntMul, NeRA, CalB
       mov ebx, NeCB
       add eax, ebx
       mov ebx, DWORD PTR 4
       invoke IntMul, eax, ebx
       mov ebx, MCAd
       add ebx, eax
       pop eax
       add [ebx],eax

       invoke dwtoa, eax, ADDR buf11
       invoke lstrcat,addr buf11,addr str11
   
       mov eax, NexCR
       mov ebx, CaRoAB 
       .BREAK .IF eax==ebx 
       inc NexCR
     .ENDW
     mov eax, NeCB
     mov ebx, CalB 
     .BREAK .IF eax==ebx 
     inc NeCB
   .ENDW
   mov eax, NeRA
   mov ebx, RowA 
   .BREAK .IF eax==ebx 
   inc NeRA
 .ENDW  
 ret
MatrProd endp
Код:
    invoke IntMul, NeRA, CalB ; IntMul - произведение целых, результат в eax
    mov ebx, NeCB
    add eax, ebx
    mov ebx, DWORD PTR 4
    invoke IntMul, eax, ebx
    mov ebx, MCAd
    add eax, ebx
Вот в таких блоках ведется поиск текущей ячейки, для последующего умножения, путем увеличения начального адреса матрицы на необходимую величину (перемещаем курсор указывающий ячейку на позицию NeRA*CalB+NeCB).

Код:
      invoke dwtoa, eax, ADDR buf11
      invoke lstrcat,addr buf11,addr str11
Здесь производится заполнение буфера только что рассчитанным значением и добавлением в него ", " (str11 = ", ")

Если необходимо, прикрепляю файл с работой.
Вложения
Тип файла: zip Работа.zip (5.8 Кб, 15 просмотров)
Ш.Р.Ю.-программист! йопта!!!
munthrekosh вне форума Ответить с цитированием
Старый 06.06.2013, 05:29   #2
munthrekosh
Пользователь
 
Аватар для munthrekosh
 
Регистрация: 12.11.2011
Сообщений: 80
По умолчанию

Несколько переработал процедуру:
Код:
.data
zpt        db ", ",0
nextstr    db 0Dh,0Ah,0
buffer1    db "Матрица С",0Dh,0Ah,0

MatrixA    DD 7, 8, 9
           DD 4, 5, 6
           DD 1, 2, 3
     
MatrixB    DD 3, 6, 9
           DD 2, 5, 1
           DD 1, 4, 1
     
MatrixC    DD 0, 0, 0
           DD 0, 0, 0
           DD 0, 0, 0

.data?
buf11         DWORD      ?
SaveAddress   DWORD      ?

MMult proc RowA: DWORD, ColumnB: DWORD, ColumnOrRowAB: DWORD 
  LOCAL NextRowA:            DWORD
  LOCAL NextColumnB:         DWORD
  LOCAL NextColumnORRowAB:   DWORD
  LOCAL CAddressSave:        DWORD

;------------------------------------------------------------
;RowA--------------количество строк матрицы А----------------
;ColumnB-----------количество столбцов матрицы В--------------
;ColumnOrRowAB-----количество столбцов А или строк В----------
;NextRowA----------счетчик номера строки А (С)----------------
;NextColumnB-------счетчик номера столбца В (С)---------------
;NextColumnORRowAB-счетчик номера столбца А и номера строки В-
;CAddressSave------переменная, которая хранит адрес ячейки С--
;-------------------------------------------------------------
  
  mov NextRowA,0         
  mov NextColumnB,0      
  mov NextColumnORRowAB,0;начинаем отсчет с нуля

while1or2:
      mov CAddressSave, 0
      invoke SearchAddress, NextRowA, ColumnB,\
             NextColumnB, ADDR MatrixC
	  xor eax, eax
	  mov eax, SaveAddress
      mov [eax], DWORD PTR 0
      mov CAddressSave, eax
      ;вычисляем адрес текущей ячейки С
      ;и вносим его в CAddressSave
while3:
        invoke SearchAddress, NextColumnORRowAB, ColumnB,\
               NextColumnB, ADDR MatrixB
        xor ebx, ebx
        mov ebx, SaveAddress
        xor eax, eax
        mov eax, [ebx]
        push eax
        ;вычисляем адрес текущей ячейки В
        ;значение из этой ячейки прячем в стэк

        invoke SearchAddress, NextRowA, ColumnOrRowAB,\
               NextColumnORRowAB, ADDR MatrixA
        xor ebx, ebx
        mov ebx, SaveAddress
        xor ecx, ecx
        mov ecx, [ebx]
        ;вычисляем адрес текущей ячейки А
        ;значение из этой ячейки в ecx
		
        xor ebx, ebx
        pop ebx
        xor eax, eax
        invoke IntMul, ecx, ebx
        ;вытаскиваем значение из стэка
        ;и помещаем его в ebx (в стэке ничего)
        ;находим произведение А[x,y]*B[y,x]
		
        xor ebx, ebx
        mov ebx, CAddressSave
        add [ebx],eax
        ;суммируем только что найденное произведение
        ;и число хранящиеся по адресу CAddressSave
		
        inc NextColumnORRowAB
        ;увеличиваем значение счетчика на 1
		
        xor eax, eax
        xor ebx, ebx
        mov eax, NextColumnORRowAB
        mov ebx, ColumnOrRowAB 
        cmp eax, ebx
        JB while3
        ;сравниваем счетчик с ColumnOrRowAB
        ;если счетчик строго меньше
        ;то цикл запускается по новой
		
        mov NextColumnORRowAB, 0 ;обнуляем счетчик
;if
          xor eax, eax
          mov eax, CAddressSave
          xor ebx, ebx
          mov ebx, [eax]
          invoke dwtoa, ebx, ADDR buf11
          invoke lstrcat, ADDR buffer1, ADDR buf11
          invoke lstrcat, ADDR buffer1, ADDR zpt
          ;вносим в буфер только что найденное значение
;endw3
      inc NextColumnB
   
      xor eax, eax
      xor ebx, ebx
      mov eax, NextColumnB
      mov ebx, ColumnB 
      cmp eax, ebx
      JB while1or2

      mov NextColumnB, 0
;endw2:
    inc NextRowA

    invoke lstrcat, ADDR buffer1, ADDR nextstr
 
    xor eax, eax
    xor ebx, ebx
    mov eax, NextRowA
    mov ebx, RowA 
    cmp eax, ebx
    JB while1or2

    mov NextRowA, 0
;endw1: 
  ret
MMult endp
;___________________________________________________

SearchAddress proc iii: DWORD, ColCount: DWORD, jjj: DWORD, MatrixAddress: DWORD

;--------------------------------------------
;iii----------номер строки-------------------
;jjj----------номер столбца------------------
;ColCount-----количество столбцов------------
;MatrixAddres-адрес первого элемента матрицы-
;--------------------------------------------

  mov SaveAddress, 0
  ;по завершению процедуры
  
  xor ebx, ebx            
  mov ebx, ColCount
  xor ecx, ecx
  mov ecx, iii
  xor eax, eax
  invoke IntMul, ebx, ecx
  ;получаем смещение адреса по строкам

  xor ecx, ecx
  mov ecx, jjj
  add ecx, eax
  ;получаем полное смещение
  
  xor ebx, ebx
  mov ebx, DWORD PTR 4
  xor eax, eax
  invoke IntMul, ecx, ebx
  ;умножаем смещение на 4
  ;т.к. двойное слово

  xor ebx, ebx
  mov ebx, MatrixAddress
  add eax, ebx
  ;получаем адрес искомой ячейки
  
  mov SaveAddress, eax
  ;сохраняем адрес
  ret
SearchAddress endp
Работает уже лучше, но все равно неправильно. А я в упор наверное не замечаю ошибки. Пожалуйста укажите, что не так.
Изображения
Тип файла: png Снимок.PNG (15.8 Кб, 46 просмотров)
Ш.Р.Ю.-программист! йопта!!!
munthrekosh вне форума Ответить с цитированием
Старый 09.06.2013, 14:22   #3
f.hump
C/C++, Asm
Участник клуба
 
Аватар для f.hump
 
Регистрация: 02.03.2010
Сообщений: 1,323
По умолчанию

если честно, то лень разбираться, что не так. могу предложить вариант для single precision column-major матриц 4х4

Код:
ALIGN 16
?MF_Multiply44@@YAXPEAMI00@Z	PROC

	MOVAPS xmm4, [rcx]
	MOVAPS xmm5, [rcx+16]
	MOVAPS xmm6, [rcx+32]
	MOVAPS xmm7, [rcx+48]

	MOVAPS xmm0, xmm4

	UNPCKLPS xmm4, xmm5
	UNPCKHPS xmm0, xmm5

	MOVAPS xmm5, xmm6

	UNPCKLPS xmm6, xmm7
	UNPCKHPS xmm5, xmm7

	MOVAPS xmm7, xmm5

	MOVHLPS xmm7, xmm0
	MOVLHPS xmm0, xmm5

	MOVAPS xmm5, xmm6
	MOVHLPS xmm5, xmm4
	MOVLHPS xmm4, xmm6

	MOVAPS xmm6, xmm0


	SUB r9, r8


align 16
	muloop:
		MOVAPS xmm0, [r8]
		
		MOVAPS xmm1, xmm0
		MOVAPS xmm2, xmm0
		MOVAPS xmm3, xmm0

		MULPS xmm0, xmm4
		MULPS xmm1, xmm5
		MULPS xmm2, xmm6
		MULPS xmm3, xmm7

		HADDPS xmm0, xmm1
		HADDPS xmm2, xmm3
		HADDPS xmm0, xmm2

		MOVNTPS [r9+r8], xmm0

		ADD r8, 16
	SUB edx, 1
	JNZ muloop

	RET
?MF_Multiply44@@YAXPEAMI00@Z	ENDP
объявлено так
Код:
extern void MF_Multiply44(float * alem, unsigned int bcount, float * blem, float * xlem);
X = A*B
А - матрица 4х4
В - матрица 4хbcount (bcount > 0)
xlem - указатель на элеметы матрицы Х
alem - указатель на элеметы матрицы А
blem - указатель на элеметы матрицы В

работать будет только в х64
переделать под х32 не составит труда

Последний раз редактировалось f.hump; 09.06.2013 в 14:33.
f.hump вне форума Ответить с цитированием
Старый 09.06.2013, 18:36   #4
munthrekosh
Пользователь
 
Аватар для munthrekosh
 
Регистрация: 12.11.2011
Сообщений: 80
По умолчанию

У меня разноразмерные матрицы =(
Ш.Р.Ю.-программист! йопта!!!
munthrekosh вне форума Ответить с цитированием
Старый 18.06.2013, 18:37   #5
munthrekosh
Пользователь
 
Аватар для munthrekosh
 
Регистрация: 12.11.2011
Сообщений: 80
По умолчанию

Это какая то дикая магия!!!
Две недели она отказывалась работать нормально. Я уже отчаялся. И тут я захожу и добавляю вот сюда.
Код:
SearchAddress proc iii: DWORD, ColCount: DWORD, jjj: DWORD, MatrixAddress: DWORD

;--------------------------------------------
;iii----------номер строки-------------------
;jjj----------номер столбца------------------
;ColCount-----количество столбцов------------
;MatrixAddres-адрес первого элемента матрицы-
;--------------------------------------------

  mov SaveAddress, 0
  ;SaveAddress - переменная, которая будет хранить адрес
  ;по завершению процедуры
  
  xor ebx, ebx            
  mov ebx, ColCount
  xor ecx, ecx
  mov ecx, iii
  xor eax, eax
  invoke IntMul, ebx, ecx
  ;умножаем количестов столбцов
  ;на номер строки и получаем
  ;необходимое смещение адреса по строкам

  xor ecx, ecx
  mov ecx, jjj
  add ecx, eax
  ;складываем смещение по строкам
  ;с номером столбца и получаем
  ;полное смещение
  
  xor ebx, ebx
  mov ebx, DWORD PTR 4
  xor eax, eax
  invoke IntMul, ecx, ebx
  ;домножаем смещение на 4
  ;т.к. двойное слово

  xor ebx, ebx
  mov ebx, MatrixAddress
  add eax, ebx
  ;складываем смещение и адресс массива
  ;получаем адрес искомой яцеки
  ;DEC eax
  mov SaveAddress, eax
  ;сохраняем адрес
  ret
SearchAddress endp
Вот эту строчку:
Код:
DEC eax
. Все стало тоьлок хуже. Вернулся и закомментил строчку. Вышел. Скомпилировал. Запустил...
И ОНА ЗАРАБОТАЛА!!!
Что это за магия такая? В чем логика?

Все что я могу сказать: Это assembler, детка.
Ш.Р.Ю.-программист! йопта!!!
munthrekosh вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Не работает процедура AVI2BMP под delphi 2010 nick17 Общие вопросы Delphi 2 19.12.2012 00:17
рамма не работает под IIS на Windows Server 2008 kocahoctpa ASP.NET 5 11.11.2012 19:42
Программа под .NET Framework 2.0 не работает на Windows 7 x64 pu4koff Общие вопросы .NET 2 13.04.2010 11:17
Assembler masm32 Светланка Помощь студентам 1 04.01.2010 18:31
Assembler, masm32 angel28 Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 3 29.12.2009 16:50