.686
.model flat, stdcall ; определяем модель памяти и
; модель вызова функций
option casemap:none ; отключаем регистрозависимость
; Библиотеки и подключаемые файлы проекта
;--------------------------------------------
include C:\masm32\include\windows.inc
include C:\masm32\include\user32.inc
include C:\masm32\include\kernel32.inc
include C:\masm32\include\masm32.inc
includelib C:\masm32\lib\user32.lib
includelib C:\masm32\lib\kernel32.lib
includelib C:\masm32\lib\masm32.lib
; Сегмент данных
;--------------------------------------------
.data
sConsTitle BYTE "Laba №4", 0
Arr DWORD 2, 2, 2, 3 ; двумерный массив 4x4
RowSize = ($ - Arr)
DWORD 2, 2, 2, 2
DWORD 1, 2, 2, 2
DWORD 2, 2, 2, 2
typeArr BYTE TYPE Arr ; размер элемента в байтах
row BYTE 4 ; число строк
col BYTE 4 ; число столбцов
i BYTE 0 ; индекс строки
j BYTE 0 ; индекс столбца
sum DWORD 0 ; переменная для хранения суммы
resultText BYTE "Answer: "
resultStr BYTE 20 DUP(?), 0
buffer BYTE 20 DUP(?), 0
tab BYTE ' ', 0
clrt BYTE 0Ah, 0Dh, 0
; Сегмент кода
;--------------------------------------------
.code
start:
; вывод заголовка консоли
invoke SetConsoleTitle, ADDR sConsTitle
; вывод массива
xor ecx, ecx ; ECX = 0
mov cl, row ; ECX = row - загружаем счётчик строк
mov esi, 0 ; ESI = 0 - указатель на нулевую строку
loop_row_1:
push ecx ; сохраняем счётчик внешнего цикла в стек
xor ecx, ecx ; ECX = 0
mov cl, col ; ECX = col - загружаем счётчик столбцов
mov ebx, 0 ; EBX = 0 - указатель на нулевой столбец
loop_col_1:
mov eax, Arr[esi][ebx] ; EAX <- Arr[i][j]
push ebx ; сохраняем регистры перед
; использованием ltoa и StdOut
push ecx
push esi
invoke ltoa, eax, ADDR buffer ; преобразование Arr[i][j] в строку
invoke StdOut, ADDR buffer ; вывод Arr[i][j]
invoke StdOut, ADDR tab ; вывод TAB
pop esi ; восстанавливаем регистры из стека
pop ecx
pop ebx
add ebx, TYPE Arr ; увеличиваем указатель столбцов на
; размер одного элемента
loop loop_col_1 ; проверяем окончание строки
invoke StdOut, ADDR clrt ; переходим на следующую строку
add esi, RowSize ; увеличиваем указатель строки на
; размер одной строки
pop ecx ; восстанавливаем счётчик внешнего цикла
loop loop_row_1 ; проверяем окончание массива
;--------------------------------------------
; вычисление произведения элементов, делящихся на 2
xor ecx, ecx ; ECX = 0
mov cl, row ; ECX = row - загружаем счётчик строк
mov esi, 0 ; ESI = 0 - указатель на нулевую строку
mov i, 0
mov sum, 1 ; начальное значение произведения
loop_row_2:
push ecx ; сохраняем счётчик внешнего цикла в стек
xor ecx, ecx ; ECX = 0
mov cl, col ; ECX = col - загружаем счётчик столбцов
mov ebx, 0 ; EBX = 0 - указатель на нулевой столбец
mov j, 0
loop_col_2:
mov eax, Arr[esi][ebx] ; EAX <- Arr[i][j]
test eax, 1 ; проверяем делится ли текущий элемент на 2
jnz not_divisible ; если не делится, переходим к следующему элементу
; умножаем текущий элемент на произведение
imul sum, eax
not_divisible:
inc j ; увеличиваем индекс столбца
add ebx, TYPE Arr ; увеличиваем указатель столбцов на размер одного элемента
loop loop_col_2 ; проверяем окончание строки
;--------------------------------------------
; вывод результата
invoke ltoa, sum, ADDR resultStr ; преобразование SUM в строку
invoke StdOut, ADDR resultText ; вывод результата
invoke Sleep, INFINITE
; завершение процессов Windows
invoke ExitProcess, NULL
; окончание сегмента start
end start
Есть ещё такой вариант, но он просто не ассемблируется