0 / 0 / 1
Регистрация: 01.08.2016
Сообщений: 11
1

Строка с максимальной суммой элементов в массиве

17.12.2016, 18:17. Показов 1652. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте, начала изучать ассемблер совсем недавно. И определенно в код закралась какая-то дурацкая ошибка.
Не могли бы вы подсказать, в чем дело?

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
.data
printf_format:
 .string "%d\n"
array:
 .long 100, 15, 148, 12, 351, 3
array_end:
m:
 .long 3
.text
.globl main
main:
  movl $0, %eax /* в %eax будет храниться результат; в начале наибольшее значение - 0 */
 movl $0, %ebx /* в %ebx находится адрес текущего элемента массива */
 movl $0, %edx /* здесь будет храниться промежуточная сумма */
 
 
loop_start: /* начало цикла */
movl m, %ecx /* количество повторов цикла sum */
 cmpl %eax, %edx /* сравнить текущую сумму с текущим наибольшим значением из %eax */
 jbe sum /* если текущий сумма меньше или равен наибольшей*/
 movl %edx, %eax /* а вот если текущая сумма превосходит наибольшую, значит, её значение и есть новый максимум */
 
sum:
addl array(,%ebx,4), %edx
incl %ebx /* увеличить %ebx на размер одного элемента массива, 4 байта */
loop sum
 
less:
cmpl $array_end, %ebx /* сравнить адрес текущего элемента и адрес конца массива */
 jae loop_end /* если они равны, выйти из цикла */
jmp loop_start
 
 
loop_end:
/*
* следующий код выводит число из %eax на экран и завершает программу
*/
 pushl %eax
 pushl $printf_format
 call printf
 addl $8, %esp
 movl $0, %eax
 ret
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.12.2016, 18:17
Ответы с готовыми решениями:

В двумерном N*K массиве целых чисел поменять строку с максимальной суммой элементов со строкой с минимальной суммой элементов.
Массив заполнять случайными числами, кроме случаев, когда это нецелесообразно (прогрессия,...

В двумерном массиве найти строку с максимальной суммой элементов
Дан двухмерный массив. Найти строку с максимальной суммой элементов.

Найти строку с максимальной суммой элементов в двумерном массиве
Найти строку с максимальной суммой элементов в двумерном массиве. Как это реализовать? Желательно...

Найти строку с максимальной суммой элементов в двумерном массиве
Найти строку с максимальной суммой элементов в двумерном массиве. Как это реализовать? Желательно...

14
Модератор
Эксперт по электронике
8384 / 4264 / 1620
Регистрация: 01.02.2015
Сообщений: 13,278
Записей в блоге: 5
17.12.2016, 19:20 2
Перед суммированием по строке не обнуляется текущая сумма (edx).
Строка 25 - комментарий правильный, но inc - всего лишь увеличение на 1. Нужно add.

Добавлено через 1 минуту

Не по теме:

Немного растерялся. Назовите, пожалуйста компилятор и ОС. Подозреваю gas и Linux.

1
0 / 0 / 1
Регистрация: 01.08.2016
Сообщений: 11
17.12.2016, 19:25  [ТС] 3
Синтаксис AT&T, да, действительно gas, Linux
0
Модератор
Эксперт по электронике
8384 / 4264 / 1620
Регистрация: 01.02.2015
Сообщений: 13,278
Записей в блоге: 5
17.12.2016, 19:31 4

Не по теме:

Sorry, за стохастические перемещения.


Но всё остальное - должно помочь.
0
0 / 0 / 1
Регистрация: 01.08.2016
Сообщений: 11
17.12.2016, 19:36  [ТС] 5
Но он ведь благодаря inc все равно проходит по каждому элементу массива...
Проблема еще была почему-то в размере массива. Написала константой и тогда проверка прошла.
Я добавила обнуление текущей суммы, но теперь у меня конечный результат - это сумма последней строки.
Хотя edx (текущая сумма) считается верно в каждой строке...

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
.data
printf_format:
 .string "%d\n"
array:
 .long 3, 20, 3, 4
array_end:
 
m:
 .long 2
.text
.globl main
main:
 movl $0, %eax /* в %eax будет храниться результат; в начале наибольшее значение - 0 */
 movl $0, %ebx /* в %ebx находится адрес текущего элемента массива */
 movl $0, %edx /* здесь будет храниться промежуточная сумма */
 
 
loop_start: /* начало цикла */
pushl %edx
 pushl $printf_format
 call printf
movl m, %ecx /* количество повторов цикла sum */
 cmpl %eax, %edx /* сравнить текущую сумму с текущим наибольшим значением из %eax */
 jbe sum /* если текущий сумма меньше или равен наибольшей*/
 movl %edx, %eax /* а вот если текущая сумма превосходит наибольшую, значит, её значение и есть новый максимум */
cmpl $4, %ebx /* сравнить адрес текущего элемента и адрес конца массива */
 jae loop_end /* если они равны, выйти из цикла */
 
 
null:
movl $0, %edx
 
sum:
addl array(,%ebx,4), %edx
incl %ebx /* увеличить %ebx на размер одного элемента массива, 4 байта */
loop sum
 
less:
jmp loop_start
 
 
loop_end:
/*
* следующий код выводит число из %eax на экран и завершает программу
*/
 pushl %eax
 pushl $printf_format
 call printf
 addl $8, %esp
 movl $0, %eax
 ret
0
Модератор
Эксперт по электронике
8384 / 4264 / 1620
Регистрация: 01.02.2015
Сообщений: 13,278
Записей в блоге: 5
17.12.2016, 20:05 6
addl array(,%ebx,4), %edx означает примерно addl array(%ebx*4), %edx. Я ошибался. Всё правильно с incl %ebx.

Вы не туда отправляете в строке 24

У вас должно быть 2 цикла. Один по строкам, и вложенный по столбцам.
Без проверки наберу, а вы проверьте
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    movl 0,%eax
    movl 0, %edx
 
loop_start: /* начало цикла */
    pushl %eax
 
    pushl %edx
    pushl $printf_format
    call printf
 
    popl %eax
 
    cmpl %eax, %edx /* сравнить текущую сумму с текущим наибольшим значением из %eax */
    jbe sum /* если текущий сумма меньше или равен наибольшей*/
    movl %edx, %eax /* а вот если текущая сумма превосходит наибольшую, значит, её значение и есть новый максимум */
    cmpl $4, %ebx /* сравнить адрес текущего элемента и адрес конца массива */
    jae loop_end /* если они равны, выйти из цикла */
sum:
    movl $0, %edx
    movl m, %ecx /* количество повторов цикла sum - цикл по столбцам в строке*/
ByString:
    addl array(,%ebx,4), %edx
    incl %ebx /* увеличить %ebx на размер одного элемента массива, 4 байта */
loop ByString
 
jmp loop_start
 
loop_end:
С адресом вместо константы у вас не получилось потому, что ebx меняется в цикле от 0 до 4, а значение array_end: равно скорее всего 4+4*4=20 - т.е. смещению от начала сегмента до метки в байтах. А это будет длина строки printf_format и длина массива.

Может быть хранить в стеке eax перед вызовом printf ?

Добавлено через 4 минуты
Адрес последнего элемента можно вычислить так
(array_end-array)/4
Assembler
1
cmpl $((array_end-array)/4), %ebx /* сравнить адрес текущего элемента и адрес конца массива */
1
0 / 0 / 1
Регистрация: 01.08.2016
Сообщений: 11
17.12.2016, 20:26  [ТС] 7
Это для отслеживания значения? Поясните, пожалуйста
Assembler
1
2
3
4
5
6
7
pushl %eax
 
    pushl %edx
    pushl $printf_format
    call printf
 
    popl %eax
Запустила, выводит сначала
0
23
7
2
Далее огромное количество нулей, потом выдает ошибку сегментирования, дамп памяти
Длина массива вычисляется верно
Весь код выглядит так:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
.data
printf_format:
 .string "%d\n"
array:
 .long 3, 20, 3, 4
array_end:
 
m:
 .long 2
.text
.globl main
main:
 movl $0, %eax /* в %eax будет храниться результат; в начале наибольшее значение - 0 */
 movl $0, %ebx /* в %ebx находится адрес текущего элемента массива */
 movl $0, %edx /* здесь будет храниться промежуточная сумма */
 
 
loop_start: /* начало цикла */
 
    pushl %eax
 
    pushl %edx
    pushl $printf_format
    call printf
 
    popl %eax
    cmpl %eax, %edx /* сравнить текущую сумму с текущим наибольшим значением из %eax */
    jbe sum /* если текущий сумма меньше или равен наибольшей*/
    movl %edx, %eax /* а вот если текущая сумма превосходит наибольшую, значит, её значение и есть новый максимум */
    cmpl $((array_end-array)/4), %ebx /* сравнить адрес текущего элемента и адрес конца массива */
    jae loop_end /* если они равны, выйти из цикла */
sum:
    movl $0, %edx
    movl m, %ecx /* количество повторов цикла sum - цикл по столбцам в строке*/
ByString:
    addl array(,%ebx,4), %edx
    incl %ebx /* увеличить %ebx на размер одного элемента массива, 4 байта */
loop ByString
 
jmp loop_start
 
loop_end:
/*
* следующий код выводит число из %eax на экран и завершает программу
*/
 pushl %eax
 pushl $printf_format
 call printf
 addl $8, %esp
 movl $0, %eax
 ret
0
Модератор
Эксперт по электронике
8384 / 4264 / 1620
Регистрация: 01.02.2015
Сообщений: 13,278
Записей в блоге: 5
17.12.2016, 20:35 8
После строки 24 нужно чистить стек? Или printf сама очищает?
0
0 / 0 / 1
Регистрация: 01.08.2016
Сообщений: 11
17.12.2016, 20:47  [ТС] 9
На сколько я знаю, функция не очищает стек от параметров. Поэтому в loop_end
Assembler
1
2
3
4
5
6
pushl %eax
 pushl $printf_format
 call printf
 addl $8, %esp
 movl $0, %eax
 ret
Прописывается строка
Assembler
1
addl $8, %esp
0
Модератор
Эксперт по электронике
8384 / 4264 / 1620
Регистрация: 01.02.2015
Сообщений: 13,278
Записей в блоге: 5
17.12.2016, 20:56 10
Вот её бы в 25 строку.
0
0 / 0 / 1
Регистрация: 01.08.2016
Сообщений: 11
17.12.2016, 21:00  [ТС] 11
Я уже добавляла, тот же результат, к сожалению.
0
Модератор
Эксперт по электронике
8384 / 4264 / 1620
Регистрация: 01.02.2015
Сообщений: 13,278
Записей в блоге: 5
17.12.2016, 21:34 12
Что-то не так с вычислением условия окончания цикла.
Хоть MinGW ставь для проверки...

Сейчас попробую набрать под masm32 и проверить под отладчиком. Если что - должно перенестись и работать нормально.

Добавлено через 1 минуту
Набрал и увидел - после сравнения в строке 28 переход на цикл суммирования, а нужно на проверку ebx.

Добавлено через 32 секунды
Ну и после printf в 25 строке очистить стек.

Добавлено через 1 минуту
Я воспользовался отладчиком под Windows - OllyDbg. Под Linux тоже должны существовать отладчики.
1
0 / 0 / 1
Регистрация: 01.08.2016
Сообщений: 11
17.12.2016, 22:07  [ТС] 13
А почему нельзя просто условие поменять на ja?
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
pushl %eax
    pushl %edx
    pushl $printf_format
    call printf
    addl $8, %esp
    popl %eax
 
    cmpl %eax, %edx /* сравнить текущую сумму с текущим наибольшим значением из %eax */
    ja sum /* если текущий сумма меньше или равен наибольшей*/
    movl %edx, %eax /* а вот если текущая сумма превосходит наибольшую, значит, её значение и есть новый максимум */
    cmpl $((array_end-array)/4), %ebx /* сравнить адрес текущего элемента и адрес конца массива */
    jae loop_end /* если они равны, выйти из цикла */
Выводит только программа, если я заменяю, как выше, конечный результат 0...
0
Модератор
Эксперт по электронике
8384 / 4264 / 1620
Регистрация: 01.02.2015
Сообщений: 13,278
Записей в блоге: 5
17.12.2016, 22:14 14
Лучший ответ Сообщение было отмечено luninok как решение

Решение

В псевдокоде должно быть
Код
  if edx>eax then
    eax:=edx;
  if ebx>=4 then
    break;
Но сейчас
Код
  if edx>eax then
  begin
    eax:=edx;
    if ebx>=4 then
      break;
  end;
Т.е. сейчас завершение цикла зависит от того, будет ли обновлён максимум. Очевидно, что это неверно.
Assembler
18
19
20
21
22
23
24
25
26
27
28
29
30
31
loop_start: /* начало цикла */
 
    pushl %edx
    pushl $printf_format
    call printf
    addl $8, %esp
 
    cmpl %eax, %edx /* сравнить текущую сумму с текущим наибольшим значением из %eax */
    jbe IndexTest /* если текущий сумма меньше или равен наибольшей*/
    movl %edx, %eax /* а вот если текущая сумма превосходит наибольшую, значит, её значение и есть новый максимум */
IndexTest:
    cmpl $((array_end-array)/4), %ebx /* сравнить адрес текущего элемента и адрес конца массива */
    jae loop_end /* если они равны, выйти из цикла */
sum:
1
0 / 0 / 1
Регистрация: 01.08.2016
Сообщений: 11
17.12.2016, 22:38  [ТС] 15
Лучший ответ Сообщение было отмечено ФедосеевПавел как решение

Решение

Огромнейшее вам спасибо за такое подробное объяснение! Все замечательно работает
И конечный код:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
.data
printf_format:
 .string "%d\n"
array:
 .long 3, 20, 3, 4
array_end:
 
m:
 .long 2
.text
.globl main
main:
 movl $0, %eax /* в %eax будет храниться результат; в начале наибольшее значение - 0 */
 movl $0, %ebx /* в %ebx находится адрес текущего элемента массива */
 movl $0, %edx /* здесь будет храниться промежуточная сумма */
 
 
loop_start: /* начало цикла */
    cmpl %eax, %edx /* сравнить текущую сумму с текущим наибольшим значением из %eax */
    jbe IndexTest /* если текущий сумма меньше или равен наибольшей*/
    movl %edx, %eax /* а вот если текущая сумма превосходит наибольшую, значит, её значение и есть новый максимум */
IndexTest:
    cmpl $((array_end-array)/4), %ebx /* сравнить адрес текущего элемента и адрес конца массива */
    jae loop_end /* если они равны, выйти из цикла */
 
sum:
    movl $0, %edx
    movl m, %ecx /* количество повторов цикла sum - цикл по столбцам в строке*/
ByString:
    addl array(,%ebx,4), %edx
    incl %ebx /* увеличить %ebx на размер одного элемента массива, 4 байта */
loop ByString
 
jmp loop_start
 
 
loop_end:
/*
* следующий код выводит число из %eax на экран и завершает программу
*/
 pushl %eax
 pushl $printf_format
 call printf
 addl $8, %esp
 movl $0, %eax
 ret
0
17.12.2016, 22:38
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
17.12.2016, 22:38
Помогаю со студенческими работами здесь

Выполнить в двумерном массиве поиск столбца с максимальной суммой элементов
Выполнить в двумерном массиве поиск столбца с максимальной суммой элементов.Помогите плиз с...

В массиве определить номер пары соседних элементов с максимальной суммой
Доброго времени суток, господа! Помогите пожалуйста в решении задачи. "В массиве из 10 чисел...

Определить в двумерном массиве строку с максимальной и столбец с минимальной суммой элементов
Определить в нем строку с максимальной и столбец с минимальной суммой элементов. Задачу решить за...

Делегаты. Найти строку в двумерном числовом массиве с максимальной суммой элементов
Найти строку в двумерном числовом массиве с максимальной суммой элементов. Модифицировать программу...

Даны три целые матрицы размера N*N. Вывести ту из них, в которой присутствует строка с максимальной суммой элементов
Доброго всем. Прошу помочь в реализации программы (Тема процедуры и функции) Даны три целые...

Изменить заданную прямоугольную матрицу так, чтобы на первом месте стояла строка с максимальной суммой элементов
Изменить заданную прямоугольную матрицу так, чтобы на первом месте стояла строка с максимальной, а...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru