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

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

ru
Offline Offline

« Ответ #30 : 03-10-2009 17:20 » 

т.к я пишу  assume  cs:cseg,ds:dseg,ss:stseg
то я использую дальнюю адресацию, правильно?
Записан
Serg79
Команда клуба

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

WWW
« Ответ #31 : 03-10-2009 17:23 » 

Да, т.к. ты явно указываешь используемый сегмент.

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

ru
Offline Offline

« Ответ #32 : 03-10-2009 17:28 » 

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

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

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

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

ru
Offline Offline

« Ответ #34 : 03-10-2009 17:36 » 

получается, что я могу убрать эту
строку (assume  cs:cseg,ds:dseg,ss:stseg) и просто указать model tiny?
Записан
Serg79
Команда клуба

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

WWW
« Ответ #35 : 03-10-2009 17:39 » 

Используй модель small.
Записан
Anarky
Постоялец

ru
Offline Offline

« Ответ #36 : 03-10-2009 17:43 » 

в книжке написано, что tiny используется для программ COM, а small
для большинства программ на ассемблере!
Записан
Serg79
Команда клуба

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

WWW
« Ответ #37 : 03-10-2009 17:45 » 

Anarky, в книжке правильно написано. Поэтому я тебе и говорю использовать small.
Записан
Anarky
Постоялец

ru
Offline Offline

« Ответ #38 : 03-10-2009 17:49 » 

я так и сделаю: получится ближняя процедура где параметры будут передаваться через регистры.
а как быть со стеком? Не понял
model flat? Здесь была моя ладья...
Записан
Serg79
Команда клуба

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

WWW
« Ответ #39 : 03-10-2009 17:51 » 

Выдели под стек 100 байт, этого тебе за глаза хватит:
Код:
.stack 100h

flat Тебе не нужен.
Записан
Anarky
Постоялец

ru
Offline Offline

« Ответ #40 : 03-10-2009 17:55 » 

если укажу flat, то получится стек гораздо больший, чем .stack 100h?
Записан
Serg79
Команда клуба

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

WWW
« Ответ #41 : 03-10-2009 18:07 » 

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

ru
Offline Offline

« Ответ #42 : 03-10-2009 18:17 » 

в книге написано:
flat: код и данные в одном 32-битном сегменте (плоская модель памяти)
Записан
Serg79
Команда клуба

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

WWW
« Ответ #43 : 03-10-2009 18:26 » 

Anarky, в книге правильно написано. Только там еще должно быть написано, что flat используется только в 32-разрядном защищенном режиме. И что бы у тебя работал код в данном режиме, должны быть определены все те селекторы про которые я тебе сказал.
Я Тебе даже больше сказу. Что бы твой код работал в защищенном режиме, помимо того что тебе надо сформировать Глобальную Таблицу Дескрипторов (GDT), тебе еще надо определить все прерывания защищенного режима и сформировать Таблицу Дескрипторов Прерываний (IDT).

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

ru
Offline Offline

« Ответ #44 : 03-10-2009 20:01 » 

Просто я тоже хочу все знать Отлично
Большое спасбо за помощь!

Все заработало!!!
Я добавил еще одно условие)))
Код:
model small
stack 256
.data
 mas   dw -3,-2,-1,0,1,2,3,4
 otv     dw ?
.code
next:  
             mov ax,@data
             mov ds,ax
             xor ax,ax
         ;mov ax,dseg
          ;mov ds,ax
;++++++++++++++++++++++++++++++++++++++++
   mov cx,8
  mov bx,offset mas
cikl:  mov ax,[bx]   ; берем элемент из массива  
      cmp ax,0            ; сравниваем ax с нулем
   jb sum                ; если меньше нуля то sum
   jge sled                ; если больше или равен то sled
  sum:
   mov otv,ax
   add dx,otv
   inc bx
   inc bx
   loop cikl
sled:
   inc bx
   inc bx
   loop cikl
;++++++++++++++++++++++++++++++++++++++++
ret
end next

Serg79, подскажи, как обратиться элементу в стеке?
Код:
model small
stack 256
.data
push -3
push -2
push -1
push 0
push 1
push 2
push 3
push 4
otv     dw ?
.code
next: 
;++++++++++++++++++++++++++++++++++++++++
   mov cx,8
cikl: 
   pop ax   ; берем элемент из стека 
   cmp ax,0            ; сравниваем ax с нулем
   jb sum                ; если меньше нуля то sum
   jge sled                ; если больше или равен то sled
  sum:
   add otv,ax
   ;add dx,otv
   ;inc bx
   ;inc bx
   loop cikl
sled:
   ;inc bx
   ;inc bx
   loop cikl
;++++++++++++++++++++++++++++++++++++++++
mov ax,4c00h
int 21h
end next
« Последнее редактирование: 04-10-2009 10:06 от Sel » Записан
RXL
Технический
Администратор

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

WWW
« Ответ #45 : 03-10-2009 21:57 » 

Anarky, для стека используй косвенную адресацию с регистром BP.

Код:
start:
    push 123 ; первый параметр
    push 456 ; второй параметр
    call sum
    add sp, 4 ; удаление параметров
    ret

sum:
    push bp
    mov bp, sp
    mov ax, [bp + 8] ; первый параметр
    mov dx, [bp + 4] ; второй параметр
    add ax, dx
    pop bp
    ret

Есть соглашение по расположению параметров в стеке: стиль pascal - параметры загружаются в прямом порядке (как в примере), стиль C - в обратном.

Заметь:
1. Параметры загружаются на стек перед вызовом подпрограммы.
2. После возвращения из подпрограммы указатель стека сдвигается на размер параметров.
3. В подпрограмме надо сохранять в начале и восстанавливать в конце значение регистра BP, т.к. он может использоваться с той же целью в вышестоящей подпрограмме.
Программа начинается с
Код:
    push bp
    mov bp, sp
и завершается
Код:
    pop bp
4. Обращение к параметрам идет по положительному смещению в порядке их помещения на стек.
5. Если нужны локальные переменные в стеке, то сперва нужно выделить под них место, проинициализировать и обращаться к ним по отрицательному смещению.
Код:
    xor ax, ax ; = 0
    push ax

; или если без инициализации
   sub sp, 2

; обращение
  mov [bp - 2], ax
6. Если используется п.5, то в конце программы нужно восстановить указатель стека.
Типовая концовка:
Код:
    mov sp, bp
    pop bp
    ret
« Последнее редактирование: 04-10-2009 06:44 от RXL » Записан

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

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

WWW
« Ответ #46 : 03-10-2009 22:25 » 

Anarky, RXL Тебе все правильно сказал. Ты должен следовать этим правилам если согласуешь свой ассемблерный код с работой программ более высокого уровня (Pascal, C ...). Если такое согласование не требуется, то ты волен сам выбирать алгоритм работы со стеком, только необходимо не забывать что с ним также работают (т.е. изменяют его вершину) и некоторые инструкции ассемблера.

Ты пробовал компилировать приведенный тобой пример из Поста 46? Зачем ты размещаешь в сегменте данных (.code) инструкции ассемблера 'push -3' ...? Это для чего? Для того чтобы работать со стеком?

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

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

WWW
« Ответ #47 : 04-10-2009 06:54 » 

В дополнение - у x86 есть команды, совмещающие в себе функционал выше описанного в п.3 и п.6.:

1) ENTER bytes, 0
Эквивалент:
Код:
push bp
mov bp, sp
sub sp, bytes

Команда имеет еще функционал, но нам он не нужен. По этому второй параметр всегда равен нулю.

2) LEAVE
Эквивалент:
Код:
mov sp, bp
pop bp

В ВУЗах их не изучают видимо потому, что их нет в i8086 — они появились в процессоре i80286.
« Последнее редактирование: 04-10-2009 06:57 от RXL » Записан

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

ru
Offline Offline

« Ответ #48 : 04-10-2009 08:35 » 

Немного почитав, я понял, что данные из стека можно брать по-разному: для этого используется отрицательное или положительное смещение...

Serg79, привет! RXL подсказал мне:
Код:
    mov ax, [bp + 12] ; первый параметр
    mov dx, [bp + 16] ; второй параметр
Почему третий и четвертый элемент будут?:
Код:
 
    mov ax, [bp + 8] ; третий параметр
    mov dx, [bp + 4] ; четвертый параметр
отрицательное смещение (понятно), а шаг 4???
« Последнее редактирование: 04-10-2009 10:03 от Sel » Записан
RXL
Технический
Администратор

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

WWW
« Ответ #49 : 04-10-2009 09:01 » 

Anarky, шаг равен размеру операнда. Для "реального режима" он равен 2 байтам. Т.ч. шаг будет 2, а не 4.
Записан

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

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

WWW
« Ответ #50 : 04-10-2009 09:06 » 

Anarky, если в стеке размещать 32 разрядные значения (eax, edx ...) то шаг 4, если 16 разрядные (ax, dx ...) тогда шаг 2.

У тебя программа работает в 16 разрядном режиме, все регистры имеют 16 разрядов и адресация 16 разрядная, значит тебе надо шаг 2.
Записан
Anarky
Постоялец

ru
Offline Offline

« Ответ #51 : 04-10-2009 09:11 » 

вот, более похоже на правду:
Код:
model small
stack 256
.data
sm  dw 16
otv  dw  ?
.code
next: 
   mov cx,8
   push -3
   push -2
   push -1
   push 0
   push 1
   push 2
   push 3
   push 4
 ;++++++++++++++++++++++++++++++++++++++++
cikl:
   mov sp,2
   mov bp,sp
   mov ax, [bp+sm]
   cmp ax,0            ; сравниваем ax с нулем
   jb sum                ; если меньше нуля то sum
   jge sled                ; если больше или равен то sled
  sum:
   add otv,ax
   add dx,otv
   sub sm,2
   pop bp
   loop cikl
sled:
   sub sm,2
   pop bp
   loop cikl
;++++++++++++++++++++++++++++++++++++++++
mov ax,4c00h
int 21h
end next
но в AX ничего не попадает, не сравнивается, не складывается((((
Записан
Serg79
Команда клуба

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

WWW
« Ответ #52 : 04-10-2009 09:11 » 

Уже начиная с процессора i386 можно работать с 32 разрядными регистрами (eax, edx, ...) и шина данных стала 32 разрядной, что позволяет адресовать до 4 Гбайт памяти. Но это все для защищенного режима. В реальном режиме можно работать только с 32 разрядными регистрами, а память так и осталась сегментной с размером сегмента 64 Кбайта.
Записан
Anarky
Постоялец

ru
Offline Offline

« Ответ #53 : 04-10-2009 09:14 » 

Меняется только BP и SP.

Подскажи, как правильно выдернуть в AX то, что мне нужно?

Я ведь недалеко от истины Да-да
« Последнее редактирование: 04-10-2009 10:07 от Sel » Записан
Serg79
Команда клуба

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

WWW
« Ответ #54 : 04-10-2009 09:17 » 

Anarky, ты зачем пытаешься разместить массив обрабатываемых данных в стеке? Это называется дергать зубы через жо.у. Для размещения заранее известных данных существует секция .date. Если тебе надо показать преподу работу со стеком, то сделай как тебе посоветовал RXL, вынеси сложение в отдельную функцию и вызывай ее, для подсчета суммы, с передачей параметров ей через стек.
Записан
RXL
Технический
Администратор

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

WWW
« Ответ #55 : 04-10-2009 09:37 » 

Цитата
Код:
mov ax, [bp+sm]

sub sm,2

Это же бред!
Скажи, ты в справочник по командам вообще смотрел?

Для 16-битной адресации возможны только такие варианты:

Группа 1 (mod 00):
[BX + SI]
[BX + DI]
[BP + SI]
[BP + DI]
[SI]
[DI]
[disp16]
[BX]

Группа 2 (mod 01):
[BX + SI + disp8]
[BX + DI + disp8]
[BP + SI + disp8]
[BP + DI + disp8]
[SI + disp8]
[DI + disp8]
[BP + disp8]
[BX + disp8]

Группа 3 (mod 10):
[BX + SI + disp16]
[BX + DI + disp16]
[BP + SI + disp16]
[BP + DI + disp16]
[SI + disp16]
[DI + disp16]
[BP + disp16]
[BX + disp16]

Т.е. обобщенно косвенный адрес состоит из суммы таких частей:
* базовый регистр BX или BP
* индексный регистр SI или DI
* целочисленное знаковое смещение размером 8 или 16 бит.
Все компоненты опциональны, но хотя бы одна должны быть. И еще отсутствуют комбинации [BP] и [disp8].

Адресация с BP использует сегмент SS, остальные — DS.

И вот на основе выше написанного объясни нам, что получится при компиляции процитированных мной строк?
« Последнее редактирование: 04-10-2009 09:46 от RXL » Записан

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

ru
Offline Offline

« Ответ #56 : 04-10-2009 12:50 » 

я запихиваю в стек 8 элементов:
Код:
  push -3
   push -2
   push -1
   push 0
   push 1
   push 2
   push 3
   push 4
вызываю подпрограмму:
Код:
call sum
add sp,2
сама подпрограмма:
Код:
sum:
   push bp
   mov bp,sp
   mov ax, [bp+2]
   cmp ax,0            ; сравниваем ax с нулем
   pop bp ; вкидывает из стека проверенный элемент
 jb go
правильно?

как посмотреть все 8 элементов?
« Последнее редактирование: 04-10-2009 12:56 от RXL » Записан
RXL
Технический
Администратор

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

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

Нет, не правильно.

Расскажи, как работает команда push.
Записан

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

ru
Offline Offline

« Ответ #58 : 04-10-2009 13:01 » 

команда push помещает в стек элемент (первый зашел, последний вышел)
я в стек помещаю восемь элементов...
команда pop берет из стека последний...
Записан
RXL
Технический
Администратор

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

WWW
« Ответ #59 : 04-10-2009 14:45 » 

Anarky, это слишком общий ответ!

SP = SP - 2 ; Указатель стека уменьшается на размер операнда.
[SP] = операнд ; Операнд помещается по адресу указателя.

Pop делает наоборот:

операнд = [SP]
SP = SP + 2

Для чего еще используется стек?
Записан

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

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines