| 
			| 
					
						| 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 »  |  | 
 
 Просто я тоже хочу все знать   Большое спасбо за помощь! Все заработало!!! Я добавил еще одно условие))) Serg79model smallstack 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
 
, подскажи, как обратиться элементу в стеке? model smallstack 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 ; = 0push 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 bpmov 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 smallstack 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 -3push -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
 
 Для чего еще используется стек?
 |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	|  |