Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: 1 2 [3] 4   Вниз
  Печать  
Автор Тема: [asm] Суммирование отрицательных членов массива  (Прочитано 79343 раз)
0 Пользователей и 15 Гостей смотрят эту тему.
Anarky
Постоялец

ru
Offline Offline

« Ответ #60 : 04-10-2009 15:46 » 

цитирую Брэдли:
Компьютер снабжает стек зарезервированным участком памяти и указателем, называемым указателем стека. Программа использует указатель стека для того, чтобы фиксировать последние помещенные в стек данные, в отличие от почты, где сами элементы очереди продвигаются вперед по мере движения очереди. В компьютере намного легче использовать для слежения за данными указатель и при записи или считывании данных из стека изменять только его. В ответ на выполнение операций POP и PUSH указатель стека соответственно увеличивается или уменьшается.
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #61 : 04-10-2009 15:49 » 

Anarky, цитировать - не велика заслуга. Попробуй своим умом думать. Вопрос я задал очень простой и если ты хоть немного знаешь материал, то ответ найдешь, а за тем и ошибку в твоем последнем листинге.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Anarky
Постоялец

ru
Offline Offline

« Ответ #62 : 04-10-2009 16:02 » 

pop bp
mov ax,bp
ax: будет элемент, который мне нужен?
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #63 : 04-10-2009 16:15 » 

Anarky, это игра-угадайка ни к чему не ведет.
Вот тебе вопрос попроще: перечисли все команды, работающие со стеком.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Anarky
Постоялец

ru
Offline Offline

« Ответ #64 : 04-10-2009 17:04 » 

call вызывает подпрограмму, сохраняя адрес возврата
ret выход из подпрограммы по сохраненному адресу возврата

Код:
model small
stack 256
.data
sm   dw 16
otv  dw  ?
.code
next:  
   push -3
   push -2
   push -1
   push 0
   push 1
   push 2
   push 3
   push 4
call sum
 sum:
     pop ax
     cmp ax,0            ; сравниваем ax с нулем
     jb go
 go:
     mov dx,otv
     add otv,ax
     ret
  jge sum                ; если больше или равен то sled

ret
end sum
mov ax,4c00h
int 21h
end next
вот к чему я пришел, но не работает Не понял
« Последнее редактирование: 06-10-2009 15:07 от Sel » Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #65 : 04-10-2009 17:33 » 

Anarky, Ты с начало объясни, что ты хочешь сделать.

Ты хочешь передавать в функцию весь массив для его суммирования или всего два элемента которые будет данная функция суммировать и возвращать результат?
Записан
Anarky
Постоялец

ru
Offline Offline

« Ответ #66 : 04-10-2009 17:35 » 

мне нужно брать элемент из стека, если отрицательный, то складывать, если 0 и больше ничего не делать: брать следующий...
Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #67 : 04-10-2009 17:40 » 

мне нужно брать элемент из стека, если отрицательный, то складывать, если 0 и больше ничего не делать: брать следующий...
Ты пойми одно.

Вызываемая функция должна ничего не знает о данных которые находятся где то там у тебя в программе. Она либо должна получать указатель на массив для суммирования и его длину, после чего она суммирует все элементы и возвращает результат. Либо второй вариант, она получает два элемента, суммирует их и возвращает результат.

Ты определись, чего ты хочешь.

Anarky, не пытайся мудрить с этим стеком.

Лично я как вижу решение твоей задачи. В основном цикле программы ты проверяешь значение из массива на отрицательное значение, если оно отрицательное то ты передаешь (через стек) данное значение и аккумулируемое значение (т.е. значение в котором накапливается результат суммирования) функции суммирования, она суммирует два значения и возвращает результат в регистре AX. И так повторяешь для всех данных в массиве.
« Последнее редактирование: 06-10-2009 15:09 от Sel » Записан
Anarky
Постоялец

ru
Offline Offline

« Ответ #68 : 04-10-2009 17:51 » 

надо взять из стека элементы, сложить отрицательные, а для этого надо указать где они хранятся в стеке...

Anarky, не пытайся мудрить с этим стеком.

Лично я как вижу решение твоей задачи. В основном цикле программы ты проверяешь значение из массива на отрицательное значение, если оно отрицательное то ты передаешь (через стек) данное значение и аккумулируемое значение (т.е. значение в котором накапливается результат суммирования) функции суммирования, она суммирует два значения и возвращает результат в регистре AX. И так повторяешь для всех данных в массиве.
именно это я и пытаюсь сделать, только массив=стек

Формально моя задача звучит так:
Составить программу, выполняющую обработку массива, аналогично заданию предыдущей работы, но оформленной в виде "ближней" процедуры, параметры в которую передаются через стек.
« Последнее редактирование: 04-10-2009 17:58 от RXL » Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #69 : 04-10-2009 17:57 » 

надо взять из стека элементы, сложить отрицательные, а для этого надо указать где они хранятся в стеке...
Это смотри сколько тебе инфы надо будет засунуть в стек: весь массив и еще индексы на отрицательные элементы. ИМХО я на месте препода да же разбираться не стал бы и сразу бы понял, что человек вообще нихрена не понимает, зачем стек нужен.

Формально моя задача звучит так:
Составить программу, выполняющую обработку массива, аналогично заданию предыдущей работы, но оформленной в виде "ближней" процедуры, параметры в которую передаются через стек.

Вот что я тебе предложил, это самый верный результат и соответствует заданию на сто процентов.
« Последнее редактирование: 06-10-2009 15:09 от Sel » Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #70 : 04-10-2009 18:03 » 

Anarky, делай проще.

надо взять из стека элементы, сложить отрицательные, а для этого надо указать где они хранятся в стеке...
Тогда передавай в функцию суммирования два значения, одно аккумулятор (это где накапливается сумма) и второе значение это элемент массива. Если элемент отрицательный то суммируй его с аккумулятором если нет то не суммируй. Результат возвращай через AX. И так для всех элементов.
Записан
Anarky
Постоялец

ru
Offline Offline

« Ответ #71 : 04-10-2009 18:04 » 

я бред написал! массив из 8ми элементов, отрицательные сложить, используя подпрограмму, данные должны передаваться через стек!
Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #72 : 04-10-2009 18:07 » 

я бред написал! массив из 8ми элементов, отрицательные сложить, используя подпрограмму, данные должны передаваться через стек!
Это тогда соответствует первому предложенному варианту, т.е. вызывается функция которой передается два значения и она их суммирует. Основной цикл вызывает при необходимости данную функцию.
Записан
Anarky
Постоялец

ru
Offline Offline

« Ответ #73 : 04-10-2009 18:15 » 

надо вставить в мою рабочую программу подпрограмму, в которой складываются значения?
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #74 : 04-10-2009 18:16 » 

Давайте вернемся чуть назад. Хочу таки пояснить, что тут происходило со стеком.

Цитата
Код:
  push -3
   push -2
   push -1
   push 0
   push 1
   push 2
   push 3
   push 4

В стек помещены данные.

Цитата
вызываю подпрограмму:
Код:
call sum

В стек помещен адрес возврата.

Цитата
сама подпрограмма:
Код:
sum:
   push bp
   mov bp,sp
   mov ax, [bp+2]
   cmp ax,0            ; сравниваем ax с нулем
   pop bp ; вкидывает из стека проверенный элемент
 jb go

Бестолковое перемешивание стека.

Цитата
вызываю подпрограмму: (повтор)
Код:
add sp,2 

Увеличение SP на 2. Очень странно - ты же 8 слов на стек положил - 16 байт!



На практике массив не загружают в стек (как это пояснил Serg79), но если параметров будет немного, то можно и через стек, но нужно обязательно передать в подпрограмму число элементов. Это получается подпрограмма с переменным числом параметров.

Код:
start:
    push -3
    push -2
    push -1
    push 0
    push 1
    push 2
    push 3
    push 4
    push 8 ; число параметров
    call sum
    add sp, 18
    ret

sum:
    push bp
    mov bp, sp
    mov cx, [bp + 4] ; загружаем количество параметров
    mov si, 6 ; начальное смещение
    xor ax, ax ; инициализация суммы
sum_1:
    add ax, [bp + si]
    add si, 2
    loop sum_1
    pop bp
    ret

Но лучше этого избегать: данные хранить в другом месте и передавать в параметрах указатель на их начало и количество элементов.

Код:
.data
argc  dw 8
args  dw -3, -2, -1, 0, 1, 2, 3, 4

.code
start:
    push [offset args]
    push [offset argc]
    call sum
    add sp, 4
    ret

sum:
    push bp
    mov bp, sp
    mov cx, [bp + 4] ; загружаем количество параметров
    mov si, [bp + 6] ; загружаем указатель на данные
    xor ax, ax ; инициализация суммы
sum_1:
    add ax, [si]
    add si, 2
    loop sum_1
    pop bp
    ret

Собственно, вот готовый код. Попробуй просто вставить в него проверку на отрицательные значения.
« Последнее редактирование: 04-10-2009 18:35 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #75 : 04-10-2009 18:17 » 

надо вставить в мою рабочую программу подпрограмму, в которой складываются значения?
Anarky, ты меня удивляешь. Очевидно же.
Записан
Anarky
Постоялец

ru
Offline Offline

« Ответ #76 : 04-10-2009 18:59 » 

Для вас очевидно! А для меня тут многое непонятно. А черт его знает...

Код:
.data
argc  dw 8
args  dw -3, -2, -1, 0, 1, 2, 3, 4

.code
start:
    push [offset args]
    push [offset argc]
    call sum
    add sp, 4 ???? закрытие параметров (что это значит??????)
    ret

sum:
    push bp
    mov bp, sp
    mov cx, [bp + 4] ; загружаем количество параметров ???? что это за параметры? и почему 4 прибавляем????
    mov si, [bp + 6] ; загружаем указатель на данные ???? вроде понятно, что это указатель, но почему +6
    xor ax, ax ; инициализация суммы ?????? это обнуление AX?????
sum_1:
    add ax, [si] ;!!!!!!! тут понятно, что в AX помещаем
    add si, 2    ;!!!!!!! следующий элемент, 2 потому что DW
    loop sum_1
    pop bp
    ret
Объясните пожалуйста! Код это хорошо, но я в нем разобраться хочу Внимание! Говорит и показывает...
« Последнее редактирование: 06-10-2009 15:06 от Sel » Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #77 : 04-10-2009 19:09 » 

Anarky честно сказать, такие вещи да же объяснять не хочется. Если ты в этом коде самостоятельно разобраться не можешь, то я не знаю чем тебе помочь.
Записан
Anarky
Постоялец

ru
Offline Offline

« Ответ #78 : 04-10-2009 19:10 » 

в универе это нах никому не надо, преподу тем более...
покажу: посмотрит, отметит...
а я ЗНАТЬ хочу!!!
Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #79 : 04-10-2009 19:12 » 

Anarky, Ты разберись что помещается в стек перед вызовом данной функции и что помещается в стек при выполнении команды call, тогда ты все поймешь.
Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #80 : 04-10-2009 19:13 » 

Anarky, ахренеть. Ты в универе учишься а с литературой работать не можешь. Ты уж извини, но исходя из твоих вопросов я думал что ты в школе учишься.
Записан
Anarky
Постоялец

ru
Offline Offline

« Ответ #81 : 04-10-2009 19:21 » 

у меня никогда не было ассемблера, литературы целый вагон, читаю конечно!
Записан
Anarky
Постоялец

ru
Offline Offline

« Ответ #82 : 04-10-2009 19:23 » 

для 4го дня неплохо))) или я безнадежен?  Флаг тебе в руки!
Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #83 : 04-10-2009 19:25 » 

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

Что толку если я тебе скажу что в функции sum в CX помещается счетчик а в SI указатель на начало массива, от этого что либо измениться или ты больше понимать станешь?
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #84 : 04-10-2009 19:31 » new

Anarky, замечательно! Хочешь знать - учи и спрашивай конкретику - мы поможем понять.

Код:
    push [offset args]
    push [offset argc]
    call sum
    add sp, 4 ???? закрытие параметров (что это значит??????)
; Закрытие? Скорее освобождение места.
; Внимательно читаем описание команды push в справочнике
;  и чрезвычайно внимательно вглядываемся в 4 (всего!) команды.

    mov cx, [bp + 4] ; загружаем количество параметров ???? что это за параметры? и почему 4 прибавляем????
    mov si, [bp + 6] ; загружаем указатель на данные ???? вроде понятно, что это указатель, но почему +6
; б##... Ниже подробно опишу.

    xor ax, ax ; инициализация суммы ?????? это обнуление AX?????
; Да. В AX храним сумму. Здесь - инициализация нулем.
; XOR сам на себя - классический способ для замены присвоения константы.

    add ax, [si] ;!!!!!!! тут понятно, что в AX помещаем
; Не помещаем! Складываем и помещаем!

    add si, 2    ;!!!!!!! следующий элемент, 2 потому что DW
; Именно! :)

Значит так. Говорим только о 16-битных командах, чтобы не путаться и не отвелекаться.

1. Регистр SP указывает на текущую вершину стека - на последнее помещенное в него значение.
2. Команды, работающие со стеком, оперируют размерами, кратными 2. При помещении значения на стек SP уменьшается на размер помещенного значения. Если не рассматривать call/ret far, прерывания и pusha/popa, то во всех остальных случаях на стек помещается или с него забирается 2-байтовое значение (слово).
3. Команда push помещает одно слово (DW) в стек.
4. Команда pop забирает одно слово со стека.
3. Команда call (near) помещает в стек адрес возврата из подпрограммы - тоже одно слово.
4. Команда ret (near) забирает одно слово - адрес возврата.

При входе в подпрограмму sum, на стеке у нас расположены:
1. адрес возврата - [SP]
2. первый параметр - [SP + 2]
3. второй параметр - [SP + 4]

После того, как мы делаем push bp, получаем:
1. BP - [SP]
2. адрес возврата - [SP + 2]
3. первый параметр - [SP + 4]
4. второй параметр - [SP + 6]

После чего мы присваиваем текущее значение SP регистру BP и используем его для доступа к параметрам.
Оттуда [BP + 4] и [BP + 6].

Теперь понятно?
« Последнее редактирование: 04-10-2009 19:33 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #85 : 04-10-2009 19:36 » 

Радуйся Anarky, что есть такие люди как RXL. Которые готовы помочь даже таким бездельникам как ты.

P.S. не обижайся Anarky, я знаю ты разберешься в этом и для тебя это станет очевидным. Ага
Записан
Anarky
Постоялец

ru
Offline Offline

« Ответ #86 : 04-10-2009 20:03 » 

я себе стек представлял как обойму в пистолете (не смейтесь)
достаем патрон, если холостой выбрасываем)))))) если боевой: кладем в карман, в AX))))))
потом смотрим сколько в кармане))))) как вам сравнение?
а тут оказывается мы ничего не достаем, ничего никуда не деваем, просто указываем откуда начинаются данные и с ними работаем Внимание! Говорит и показывает...
А вы ребята молодцы, вам спасибо, респект и уважуха))) завтра попробую все в одну кучу собрать и заставить работать!
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #87 : 04-10-2009 20:39 » 

Anarky, карман у нас не резиновый и потому в нем только одно значение. В целом, сравнение неплохое. Только стек здесь не имеет конца: SP - это просто смещение в сегменте SS и когда SP дойдет до любого края, он перейдет на другую сторону.

Все данные хранятся в памяти - стек в том числе - вопрос только как к ним подступиться.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Anarky
Постоялец

ru
Offline Offline

« Ответ #88 : 05-10-2009 06:58 » 

RXL а почему мы не можем просто указать
Код:
mov cx,8
мы пишем
Код:
mov cx, [bp+4]
в подпрограмме sum после push:
1. BP - [SP] ; команда push поместила слово
2. [SP + 2]  ; адрес возврата
3. [SP + 4]  ; указатель массива
4. [SP + 6]  ; элемент в массиве
5. add si, 2 ; просматриваем следующий элемент массива
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #89 : 05-10-2009 07:36 » 

Anarky, откуда твоя подпрограмма знает, сколько элементов в массиве? Хадр-кодед - это большое зло. Значит может узнать только из параметров.

мы пишем
Код:
mov cx, [bp+4]
в подпрограмме sum после push:
1. BP - [SP] ; команда push поместила слово
2. [SP + 2]  ; адрес возврата
3. [SP + 4]  ; указатель массива
4. [SP + 6]  ; элемент в массиве
5. add si, 2 ; просматриваем следующий элемент массива

Неверно!

1. push [offset args]
+0 указатель

2. push [offset argc]
+0 размер массива
+2 указатель

3. call sum
+0 адрес возврата
+2 размер массива
+4 указатель

4. push bp
+0 сохраненное значение BP
+2 адрес возврата
+4 размер массива
+6 указатель

Напоминаю про соглашение о порядке помещения аргументов в стек!
Стиль Си: push в обратном порядке, а в памяти они в прямом порядке.
Стиль Паскаль: push в прямом порядке, а в памяти они в обратном порядке.

Стиль pascal исключает возможность иметь переменное число параметров, предусмотренное в языке Си.
В примере я использовал стиль Си.
« Последнее редактирование: 05-10-2009 07:38 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: 1 2 [3] 4   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines