Anarky
Постоялец
Offline
|
|
« Ответ #30 : 03-10-2009 17:20 » |
|
т.к я пишу assume cs:cseg,ds:dseg,ss:stseg то я использую дальнюю адресацию, правильно?
|
|
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #31 : 03-10-2009 17:23 » |
|
Да, т.к. ты явно указываешь используемый сегмент.
Anarky, ты начинаешь распыляться на второстепенные вещи. Ты с начало реши поставленную перед тобой задачу, а потом уже начинай изучать углубленный материал.
|
|
|
Записан
|
|
|
|
Anarky
Постоялец
Offline
|
|
« Ответ #32 : 03-10-2009 17:28 » |
|
для меня это очень актуально! преподаватель сказал, чтоб я использовал ближние процедуры, параметры в которую передаются через регистры и стек. одна программа через регистры, вторая через стек!
|
|
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #33 : 03-10-2009 17:33 » |
|
Если Ты явно не указываешь сегмент то всегда используется ближний вызов.
|
|
|
Записан
|
|
|
|
Anarky
Постоялец
Offline
|
|
« Ответ #34 : 03-10-2009 17:36 » |
|
получается, что я могу убрать эту строку (assume cs:cseg,ds:dseg,ss:stseg) и просто указать model tiny?
|
|
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #35 : 03-10-2009 17:39 » |
|
Используй модель small.
|
|
|
Записан
|
|
|
|
Anarky
Постоялец
Offline
|
|
« Ответ #36 : 03-10-2009 17:43 » |
|
в книжке написано, что tiny используется для программ COM, а small для большинства программ на ассемблере!
|
|
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #37 : 03-10-2009 17:45 » |
|
Anarky, в книжке правильно написано. Поэтому я тебе и говорю использовать small.
|
|
|
Записан
|
|
|
|
Anarky
Постоялец
Offline
|
|
« Ответ #38 : 03-10-2009 17:49 » |
|
я так и сделаю: получится ближняя процедура где параметры будут передаваться через регистры. а как быть со стеком? model flat?
|
|
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #39 : 03-10-2009 17:51 » |
|
Выдели под стек 100 байт, этого тебе за глаза хватит: flat Тебе не нужен.
|
|
|
Записан
|
|
|
|
Anarky
Постоялец
Offline
|
|
« Ответ #40 : 03-10-2009 17:55 » |
|
если укажу flat, то получится стек гораздо больший, чем .stack 100h?
|
|
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #41 : 03-10-2009 18:07 » |
|
Anarky, если ты укажешь flat то у тебя сегментов вообще не будет. В сегментных регистрах тогда у тебя должны быть указатели соответственно на селектор кода, селектор данных и селектор стека, а данные селекторы должны находится в глобальной таблице селекторов на которую должен указывать регистр IDTR.
|
|
|
Записан
|
|
|
|
Anarky
Постоялец
Offline
|
|
« Ответ #42 : 03-10-2009 18:17 » |
|
в книге написано: flat: код и данные в одном 32-битном сегменте (плоская модель памяти)
|
|
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #43 : 03-10-2009 18:26 » |
|
Anarky, в книге правильно написано. Только там еще должно быть написано, что flat используется только в 32-разрядном защищенном режиме. И что бы у тебя работал код в данном режиме, должны быть определены все те селекторы про которые я тебе сказал. Я Тебе даже больше сказу. Что бы твой код работал в защищенном режиме, помимо того что тебе надо сформировать Глобальную Таблицу Дескрипторов (GDT), тебе еще надо определить все прерывания защищенного режима и сформировать Таблицу Дескрипторов Прерываний (IDT).
P.S. Anarky, ты что то далеко начинаешь уходить от поставленной тебе задачи.
|
|
|
Записан
|
|
|
|
Anarky
Постоялец
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
|
|
« Ответ #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, т.к. он может использоваться с той же целью в вышестоящей подпрограмме. Программа начинается с и завершается 4. Обращение к параметрам идет по положительному смещению в порядке их помещения на стек. 5. Если нужны локальные переменные в стеке, то сперва нужно выделить под них место, проинициализировать и обращаться к ним по отрицательному смещению. xor ax, ax ; = 0 push ax
; или если без инициализации sub sp, 2
; обращение mov [bp - 2], ax
6. Если используется п.5, то в конце программы нужно восстановить указатель стека. Типовая концовка:
|
|
« Последнее редактирование: 04-10-2009 06:44 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Serg79
|
|
« Ответ #46 : 03-10-2009 22:25 » |
|
Anarky, RXL Тебе все правильно сказал. Ты должен следовать этим правилам если согласуешь свой ассемблерный код с работой программ более высокого уровня (Pascal, C ...). Если такое согласование не требуется, то ты волен сам выбирать алгоритм работы со стеком, только необходимо не забывать что с ним также работают (т.е. изменяют его вершину) и некоторые инструкции ассемблера. Ты пробовал компилировать приведенный тобой пример из Поста 46? Зачем ты размещаешь в сегменте данных (.code) инструкции ассемблера 'push -3' ...? Это для чего? Для того чтобы работать со стеком? Для инициализированных данных, такие как массивы и переменные, используют сегмент данных а не стек. Стек используют для хранения автоматически создаваемых переменных необходимых в функциях и для хранения промежуточных значений, и как RXL заметил, для передачи параметров вызываемым функциям в языках высокого уровня.
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #47 : 04-10-2009 06:54 » |
|
В дополнение - у x86 есть команды, совмещающие в себе функционал выше описанного в п.3 и п.6.: 1) ENTER bytes, 0Эквивалент: push bp mov bp, sp sub sp, bytes
Команда имеет еще функционал, но нам он не нужен. По этому второй параметр всегда равен нулю. 2) LEAVEЭквивалент: В ВУЗах их не изучают видимо потому, что их нет в i8086 — они появились в процессоре i80286.
|
|
« Последнее редактирование: 04-10-2009 06:57 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Anarky
Постоялец
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
|
|
« Ответ #49 : 04-10-2009 09:01 » |
|
Anarky, шаг равен размеру операнда. Для "реального режима" он равен 2 байтам. Т.ч. шаг будет 2, а не 4.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Serg79
|
|
« Ответ #50 : 04-10-2009 09:06 » |
|
Anarky, если в стеке размещать 32 разрядные значения (eax, edx ...) то шаг 4, если 16 разрядные (ax, dx ...) тогда шаг 2.
У тебя программа работает в 16 разрядном режиме, все регистры имеют 16 разрядов и адресация 16 разрядная, значит тебе надо шаг 2.
|
|
|
Записан
|
|
|
|
Anarky
Постоялец
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
|
|
« Ответ #52 : 04-10-2009 09:11 » |
|
Уже начиная с процессора i386 можно работать с 32 разрядными регистрами (eax, edx, ...) и шина данных стала 32 разрядной, что позволяет адресовать до 4 Гбайт памяти. Но это все для защищенного режима. В реальном режиме можно работать только с 32 разрядными регистрами, а память так и осталась сегментной с размером сегмента 64 Кбайта.
|
|
|
Записан
|
|
|
|
Anarky
Постоялец
Offline
|
|
« Ответ #53 : 04-10-2009 09:14 » |
|
Меняется только BP и SP. Подскажи, как правильно выдернуть в AX то, что мне нужно? Я ведь недалеко от истины
|
|
« Последнее редактирование: 04-10-2009 10:07 от Sel »
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #54 : 04-10-2009 09:17 » |
|
Anarky, ты зачем пытаешься разместить массив обрабатываемых данных в стеке? Это называется дергать зубы через жо.у. Для размещения заранее известных данных существует секция .date. Если тебе надо показать преподу работу со стеком, то сделай как тебе посоветовал RXL, вынеси сложение в отдельную функцию и вызывай ее, для подсчета суммы, с передачей параметров ей через стек.
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #55 : 04-10-2009 09:37 » |
|
Это же бред! Скажи, ты в справочник по командам вообще смотрел? Для 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
Постоялец
Offline
|
|
« Ответ #56 : 04-10-2009 12:50 » |
|
я запихиваю в стек 8 элементов: 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
правильно? как посмотреть все 8 элементов?
|
|
« Последнее редактирование: 04-10-2009 12:56 от RXL »
|
Записан
|
|
|
|
RXL
|
|
« Ответ #57 : 04-10-2009 12:57 » |
|
Нет, не правильно.
Расскажи, как работает команда push.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Anarky
Постоялец
Offline
|
|
« Ответ #58 : 04-10-2009 13:01 » |
|
команда push помещает в стек элемент (первый зашел, последний вышел) я в стек помещаю восемь элементов... команда pop берет из стека последний...
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #59 : 04-10-2009 14:45 » |
|
Anarky, это слишком общий ответ!
SP = SP - 2 ; Указатель стека уменьшается на размер операнда. [SP] = операнд ; Операнд помещается по адресу указателя.
Pop делает наоборот:
операнд = [SP] SP = SP + 2
Для чего еще используется стек?
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
|