Anarky
Постоялец
Offline
|
|
« Ответ #60 : 04-10-2009 15:46 » |
|
цитирую Брэдли: Компьютер снабжает стек зарезервированным участком памяти и указателем, называемым указателем стека. Программа использует указатель стека для того, чтобы фиксировать последние помещенные в стек данные, в отличие от почты, где сами элементы очереди продвигаются вперед по мере движения очереди. В компьютере намного легче использовать для слежения за данными указатель и при записи или считывании данных из стека изменять только его. В ответ на выполнение операций POP и PUSH указатель стека соответственно увеличивается или уменьшается.
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #61 : 04-10-2009 15:49 » |
|
Anarky, цитировать - не велика заслуга. Попробуй своим умом думать. Вопрос я задал очень простой и если ты хоть немного знаешь материал, то ответ найдешь, а за тем и ошибку в твоем последнем листинге.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Anarky
Постоялец
Offline
|
|
« Ответ #62 : 04-10-2009 16:02 » |
|
pop bp mov ax,bp ax: будет элемент, который мне нужен?
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #63 : 04-10-2009 16:15 » |
|
Anarky, это игра-угадайка ни к чему не ведет. Вот тебе вопрос попроще: перечисли все команды, работающие со стеком.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Anarky
Постоялец
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
|
|
« Ответ #65 : 04-10-2009 17:33 » |
|
Anarky, Ты с начало объясни, что ты хочешь сделать.
Ты хочешь передавать в функцию весь массив для его суммирования или всего два элемента которые будет данная функция суммировать и возвращать результат?
|
|
|
Записан
|
|
|
|
Anarky
Постоялец
Offline
|
|
« Ответ #66 : 04-10-2009 17:35 » |
|
мне нужно брать элемент из стека, если отрицательный, то складывать, если 0 и больше ничего не делать: брать следующий...
|
|
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #67 : 04-10-2009 17:40 » |
|
мне нужно брать элемент из стека, если отрицательный, то складывать, если 0 и больше ничего не делать: брать следующий...
Ты пойми одно. Вызываемая функция должна ничего не знает о данных которые находятся где то там у тебя в программе. Она либо должна получать указатель на массив для суммирования и его длину, после чего она суммирует все элементы и возвращает результат. Либо второй вариант, она получает два элемента, суммирует их и возвращает результат. Ты определись, чего ты хочешь. Anarky, не пытайся мудрить с этим стеком. Лично я как вижу решение твоей задачи. В основном цикле программы ты проверяешь значение из массива на отрицательное значение, если оно отрицательное то ты передаешь (через стек) данное значение и аккумулируемое значение (т.е. значение в котором накапливается результат суммирования) функции суммирования, она суммирует два значения и возвращает результат в регистре AX. И так повторяешь для всех данных в массиве.
|
|
« Последнее редактирование: 06-10-2009 15:09 от Sel »
|
Записан
|
|
|
|
Anarky
Постоялец
Offline
|
|
« Ответ #68 : 04-10-2009 17:51 » |
|
надо взять из стека элементы, сложить отрицательные, а для этого надо указать где они хранятся в стеке... Anarky, не пытайся мудрить с этим стеком.
Лично я как вижу решение твоей задачи. В основном цикле программы ты проверяешь значение из массива на отрицательное значение, если оно отрицательное то ты передаешь (через стек) данное значение и аккумулируемое значение (т.е. значение в котором накапливается результат суммирования) функции суммирования, она суммирует два значения и возвращает результат в регистре AX. И так повторяешь для всех данных в массиве.
именно это я и пытаюсь сделать, только массив=стек Формально моя задача звучит так: Составить программу, выполняющую обработку массива, аналогично заданию предыдущей работы, но оформленной в виде "ближней" процедуры, параметры в которую передаются через стек.
|
|
« Последнее редактирование: 04-10-2009 17:58 от RXL »
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #69 : 04-10-2009 17:57 » |
|
надо взять из стека элементы, сложить отрицательные, а для этого надо указать где они хранятся в стеке...
Это смотри сколько тебе инфы надо будет засунуть в стек: весь массив и еще индексы на отрицательные элементы. ИМХО я на месте препода да же разбираться не стал бы и сразу бы понял, что человек вообще нихрена не понимает, зачем стек нужен. Формально моя задача звучит так: Составить программу, выполняющую обработку массива, аналогично заданию предыдущей работы, но оформленной в виде "ближней" процедуры, параметры в которую передаются через стек.
Вот что я тебе предложил, это самый верный результат и соответствует заданию на сто процентов.
|
|
« Последнее редактирование: 06-10-2009 15:09 от Sel »
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #70 : 04-10-2009 18:03 » |
|
Anarky, делай проще. надо взять из стека элементы, сложить отрицательные, а для этого надо указать где они хранятся в стеке... Тогда передавай в функцию суммирования два значения, одно аккумулятор (это где накапливается сумма) и второе значение это элемент массива. Если элемент отрицательный то суммируй его с аккумулятором если нет то не суммируй. Результат возвращай через AX. И так для всех элементов.
|
|
|
Записан
|
|
|
|
Anarky
Постоялец
Offline
|
|
« Ответ #71 : 04-10-2009 18:04 » |
|
я бред написал! массив из 8ми элементов, отрицательные сложить, используя подпрограмму, данные должны передаваться через стек!
|
|
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #72 : 04-10-2009 18:07 » |
|
я бред написал! массив из 8ми элементов, отрицательные сложить, используя подпрограмму, данные должны передаваться через стек!
Это тогда соответствует первому предложенному варианту, т.е. вызывается функция которой передается два значения и она их суммирует. Основной цикл вызывает при необходимости данную функцию.
|
|
|
Записан
|
|
|
|
Anarky
Постоялец
Offline
|
|
« Ответ #73 : 04-10-2009 18:15 » |
|
надо вставить в мою рабочую программу подпрограмму, в которой складываются значения?
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #74 : 04-10-2009 18:16 » |
|
Давайте вернемся чуть назад. Хочу таки пояснить, что тут происходило со стеком. push -3 push -2 push -1 push 0 push 1 push 2 push 3 push 4
В стек помещены данные. В стек помещен адрес возврата. сама подпрограмма: sum: push bp mov bp,sp mov ax, [bp+2] cmp ax,0 ; сравниваем ax с нулем pop bp ; вкидывает из стека проверенный элемент jb go
Бестолковое перемешивание стека. вызываю подпрограмму: (повтор) Увеличение 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
|
|
« Ответ #75 : 04-10-2009 18:17 » |
|
надо вставить в мою рабочую программу подпрограмму, в которой складываются значения?
Anarky, ты меня удивляешь. Очевидно же.
|
|
|
Записан
|
|
|
|
Anarky
Постоялец
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
|
|
« Ответ #77 : 04-10-2009 19:09 » |
|
Anarky честно сказать, такие вещи да же объяснять не хочется. Если ты в этом коде самостоятельно разобраться не можешь, то я не знаю чем тебе помочь.
|
|
|
Записан
|
|
|
|
Anarky
Постоялец
Offline
|
|
« Ответ #78 : 04-10-2009 19:10 » |
|
в универе это нах никому не надо, преподу тем более... покажу: посмотрит, отметит... а я ЗНАТЬ хочу!!!
|
|
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #79 : 04-10-2009 19:12 » |
|
Anarky, Ты разберись что помещается в стек перед вызовом данной функции и что помещается в стек при выполнении команды call, тогда ты все поймешь.
|
|
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #80 : 04-10-2009 19:13 » |
|
Anarky, ахренеть. Ты в универе учишься а с литературой работать не можешь. Ты уж извини, но исходя из твоих вопросов я думал что ты в школе учишься.
|
|
|
Записан
|
|
|
|
Anarky
Постоялец
Offline
|
|
« Ответ #81 : 04-10-2009 19:21 » |
|
у меня никогда не было ассемблера, литературы целый вагон, читаю конечно!
|
|
|
Записан
|
|
|
|
|
Serg79
|
|
« Ответ #83 : 04-10-2009 19:25 » |
|
у меня никогда не было ассемблера, литературы целый вагон, читаю конечно!
Anarky, поэтому я тебе и говорю: разбирайся и читай учебники. Что толку если я тебе скажу что в функции sum в CX помещается счетчик а в SI указатель на начало массива, от этого что либо измениться или ты больше понимать станешь?
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #84 : 04-10-2009 19:31 » |
|
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
|
|
« Ответ #85 : 04-10-2009 19:36 » |
|
Радуйся Anarky, что есть такие люди как RXL. Которые готовы помочь даже таким бездельникам как ты. P.S. не обижайся Anarky, я знаю ты разберешься в этом и для тебя это станет очевидным.
|
|
|
Записан
|
|
|
|
Anarky
Постоялец
Offline
|
|
« Ответ #86 : 04-10-2009 20:03 » |
|
я себе стек представлял как обойму в пистолете (не смейтесь) достаем патрон, если холостой выбрасываем)))))) если боевой: кладем в карман, в AX)))))) потом смотрим сколько в кармане))))) как вам сравнение? а тут оказывается мы ничего не достаем, ничего никуда не деваем, просто указываем откуда начинаются данные и с ними работаем А вы ребята молодцы, вам спасибо, респект и уважуха))) завтра попробую все в одну кучу собрать и заставить работать!
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #87 : 04-10-2009 20:39 » |
|
Anarky, карман у нас не резиновый и потому в нем только одно значение. В целом, сравнение неплохое. Только стек здесь не имеет конца: SP - это просто смещение в сегменте SS и когда SP дойдет до любого края, он перейдет на другую сторону.
Все данные хранятся в памяти - стек в том числе - вопрос только как к ним подступиться.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Anarky
Постоялец
Offline
|
|
« Ответ #88 : 05-10-2009 06:58 » |
|
RXL а почему мы не можем просто указать мы пишем в подпрограмме sum после push: 1. BP - [SP] ; команда push поместила слово 2. [SP + 2] ; адрес возврата 3. [SP + 4] ; указатель массива 4. [SP + 6] ; элемент в массиве 5. add si, 2 ; просматриваем следующий элемент массива
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #89 : 05-10-2009 07:36 » |
|
Anarky, откуда твоя подпрограмма знает, сколько элементов в массиве? Хадр-кодед - это большое зло. Значит может узнать только из параметров. мы пишем в подпрограмме 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 »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
|