WMmail.ru - сервис почтовых рассылок

вторник, 26 июня 2012 г.

RFpro.ru: Ассемблер? Это просто! Учимся программировать

 
Если выпуск не отображается, вы можете прочесть его на сайте Отказаться от рекламы
  
  
  

  Мои подписки      Мои группы      Мои новости     
        Автор 
Калашников О.А.
      
  
Компьютеры и интернет   →   Софт   →   Программирование   →   RFpro.ru: Ассемблер? Это просто! Учимся программировать
  
RFpro.ru: Ассемблер? Это просто! Учимся программировать
 
 

Хостинг портала RFpro.ru:
Московский хостер
Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64

РАССЫЛКИ ПОРТАЛА RFPRO.RU

Лучшие эксперты по данной тематике

Асмик Гаряка
Статус: Советник
Рейтинг: 10973
• повысить рейтинг »
Коцюрбенко Алексей aka Жерар
Статус: Советник
Рейтинг: 4360
• повысить рейтинг »
Boriss
Статус: Академик
Рейтинг: 2257
• повысить рейтинг »

/ КОМПЬЮТЕРЫ И СОФТ / Программирование / Assembler (Ассемблер)

Номер выпуска:1528
Дата выхода:26.06.2012, 16:00
Администратор рассылки:Лысков Игорь Витальевич (Старший модератор)
Подписчиков / экспертов:91 / 34
Вопросов / ответов:1 / 1

Консультация # 186409: Уважаемые эксперты! Пожалуйста, ответьте на вопрос: требуется написать программу для ТАSM для вычисления данных выражений. Каждую функцию реализовать в виде отдельной подпрограммы, используя наиболее подходящий спос...


Консультация # 186409:

Уважаемые эксперты! Пожалуйста, ответьте на вопрос:
требуется написать программу для ТАSM для вычисления данных выражений.

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

Когда то я уже задавал подобрый вопрос и он есть у меня в истории. Требуется написать так программу, чтобы она была весьма простой и максимально откоментированной.
В прошлой программе громоздким считать нужно таблицы для вывода степеней(окончание программы).Буду очень рад если сможете написать все это в максимально возможные сроки.
Спасибо! smile

Дата отправки: 23.06.2012, 15:28
Вопрос задал: Юдин Евгений Сергеевич (Студент)
Всего ответов: 1
Страница онлайн-консультации »


Консультирует Лысков Игорь Витальевич (Старший модератор):

Здравствуйте, Юдин Евгений Сергеевич!
Работу с вещественными числами, в любом случае, простой не назовешь...
Раз Вам не понравилось, как сделано в masm-е, я сделал по-другому smile
Надеюсь, что такое решение Вас устроит... smile
Имейте в виду, что при вводе переменных необходимо следить, чтобы выражение под корнем было >= 0

Код :
 	.model	small, stdcall 	.386					;необходимо для команды fcos  ;макро для вычисления y^x ;в st должно находиться xlog[2]y POWER	MACRO 	fld	st				;x*log[2]y->st(1) 	frndint					;округляем st до целого 	fsub	st(1),st			;st(1)-=st 	fxch					;st(1)<->st 	f2xm1					;st=(2 в степени st) - 1 	fld1					;1->st 	fadd					;st+=1 	fscale					;y^x = st * (2 в степени st(1)) 	fstp	st(1)				;чтобы убрать значение из st(1) 	ENDM  ;e^st ;st = z EXP	MACRO 	fldl2e					;log(осн 2)e->st 	fmulp					;st(1)*log(осн 2)e->st 	POWER					;st=e^(st) 	ENDM  ;log[3](st) LOG3	MACRO 	fld1					;1 	fxch					;st(1)<->st 	fyl2x					;st=1*log[2]st=log[2]y 	fld1					;1 	fld	c3				;3 	fyl2x					;st=1*log[2]3=log[2]3 	fdiv					;st=st(1)/st=log[2]x/log[2]3=log[3]y 	ENDM  ;((log[3](y))^2-z)^(1/5) CALC_YZ	MACRO	yoff,zoff 	lea	bx,y				;address y 	fld	dword ptr [bx]			;y->st 	LOG3					;st=log[3]y 	fld	st				;st=st(1) 	fmulp					;st=log[3]y^2 	lea	bx,z				;address z 	fsub	dword ptr [bx]			;st=log[3]y^2-z ;возведем в степень 1/5 	fld1					;1 	fdiv	c5				;1/5 	fxch					;st(1)<->st 	fyl2x					;st=st(1)*log[2]st 	POWER					;находим (log[3](y)^2-z)^(1/5) 	ENDM	  	.code start: 	mov	ax, @data 	mov	ds, ax				;настроим сегментные регистры 	mov	es, ax				;на сегмент @data 	mov	ss, ax 	mov	sp, 0fffeh			;стек в вершине 						;введем данные x_loop: 	lea	si, sEnterX			;строка приглашения 	call	GetFloat			;вводим вещественное, результат в st 	jc	x_loop				;С=1 - ошибка формата! На повтор ввода! 	fstp	x				;сохраним в x y_loop: 	lea	si, sEnterY 	call	GetFloat 	jc	y_loop 	fstp	y				;y z_loop: 	lea	si, sEnterZ 	call	GetFloat 	jc	z_loop 	fstp	z				;z  	call	calc_a				;получаем в st расчет a 	fst	a				;сохраним в a и оставим в st(0) 	push	offset sNum			;адрес буфера для числовой строки 	call	float2str			;преобразовываем вещественное число из st(0) 	lea	si, sA				;строка пояснения 'a=' 	lea	bx, sNum			;числовая строка 	call	prStr				;выводим две строки [si]+[bx]  	call	calc_b				;получаем в st расчет b 	fst	b				;сохраним в b и оставим в st(0) 	push	offset sNum			;адрес буфера для числовой строки 	call	float2str			;преобразовываем вещественное число из st(0) 	lea	si, sB				;строка пояснения 'b=' 	lea	bx, sNum			;числовая строка 	call	prStr				;выводим две строки [si]+[bx]  	lea	si, sAny			;Press any key 	call	prsz				;выводим строку из si  	mov	ah, 0				;ждем any key 	int	16h  	mov	ax,4c00h 	int	21h				;выход в ДОС  GetFloat	proc				;ввод вещественного числа 	call	prsz				;выводим приглашение из si 	lea	dx, sBuf 	mov	ah, 0ah 	int	21h				;вводим строку 	lea	ax, string			;адрес строки 	push	ax				;параметр в стек 	call	str2float			;преобразовываем в вещественное 	ret					;число в st(0) GetFloat	endp  prsz	proc					;вывод стоки ASCIIZ [si] 	lodsb 	cmp	al, 0 	je	prret 	int	29h 	jmp	prsz prret: 	ret prsz	endp  prStr	proc	near				;вывод двух строк ASCIIZ 	call	prsz				;первая [si] 	mov	si, bx 	call	prsz				;вторая [bx] 	ret prStr	endp  ;расчет a ;результат в st calc_a	proc 	fld	x				;st = x 	fmul	c3				;st = 3*x 	fcos					;st = cos(3x) 	fld	st				;st(1) = st 	fmulp					;st = cos(3x)^2 	fmul	c008				;st = 0.08*cos(3x)^2 	fld	z				;st = z 	EXP					;st = e^z 	fsubp	st(1),st			;st = 0.08*cos(3x)^2 - e^z 	CALC_YZ					;st = (log[3](y)^2 - z)^(1/5) 	fld	z				;st = z 	fmul	C7				;st = 7z 	faddp					;st = (log[3](y)^2 - z)^(1/5) + 7z 	fdivp					;st = (0.08*cos(3x)^2 - e^z)/ 	ret					;     ((log[3](y)^2 - z)^(1/5) + 7z) calc_a	endp  ;расчет b ;результат в st calc_b	proc 	CALC_YZ					;st = (log[3](y)^2 - z)^(1/5) 	fld	y				;st = y 	fmul	C5				;st = 5y 	fsubp					;st = (log[3](y)^2 - z)^(1/5) - 5y 	fadd	C00006				;st = (log[3](y)^2 - z)^(1/5) - 5y + 0.00006 	ret calc_b	endp  ;----------------------------------------- ;П/п конвертации float <-> ASCII ;-----------------------------------------  ;преобразование вещественного числа-строки во float ;если строка некорректна, то возвращается C=1 str2float	proc	uses si di, numstr:word local	numfloat:dword, c10num:word, nextnum:word, order:word  ;будем накапивать число в регистре сопроцессора, начинаем с нуля 	fldz ;будем умножать/делить на 10 	mov	c10num, 10 ;порядок = 0 	mov	order, 0 ;dl=0/1 - положительное/отрицательное число, dh=1 - знак задан 	xor	dx, dx ;cl=0/1 - целая/дробная часть, ch=1 - точка задана 	xor	cx, cx ;bl=0/1 - положительная/отрицательная степень после Е, bh=1 - степень задана 	xor	bx, bx ;адрес строки 	mov	si, numstr sym_loop: 	xor	ax, ax 	lodsb 	cmp	al, 0dh 	je	set_order	;строка кончилась 	cmp	al, 0 	je	set_order	;строка кончилась 	cmp	al, '+' 	je	plus_sign	;+ 	cmp	al, '-' 	je	minus_sign	;- 	cmp	al, '.' 	je	point_sign	;. 	cmp	al, 'e' 	je	order_sign	;e 	cmp	al, 'E' 	je	order_sign	;E 	cmp	al, '0' 	jb	num_err		;ошибка - не цифра 	cmp	al, '9' 	ja	num_err 	sub	al, '0'		;'0'-'9' -> 0-9 	mov	nextnum, ax	;сохраним слово в памяти 	mov	dh, 1		;после цифры задавать знак числа нельзя! 	cmp	bh, 0		;вводим порядок? 	jne	num_order 				;нет, вводим мантиссу 	jcxz	part_integer	;точки еще не было - целая часть числа part_broken:			;дробная часть 	fld	numfloat	;вес цифры: 0.1, 0.001, 0.0001,... 	fimul	nextnum	 	;умножаем на цифру 	faddp			;и добавляем до числа 	fld	numfloat	;формируем вес следующей цифры 	fidiv	c10num 	fstp	numfloat 	jmp	sym_loop num_order:			;вводим порядок 	mov	ax, 10		;вводим до конца строки двоичное число 	mul	order 	add	ax, nextnum 	mov	order, ax 	jmp	sym_loop  num_err:			;ошибка (любая) 	fstp	numfloat	;уберем из сопроцессора число 	stc			;признак ошибки 	jmp	str2float_ret	;на общий выход (чтобы подправить стек)  part_integer:			;целая часть 	fimul	c10num		;умножаем на 10 	fiadd	nextnum		;и добавляем цифру 	jmp	sym_loop  plus_sign:			;+ 	cmp	bh, 0		;вводим порядок? 	jne	plus_order	 				;нет, вводим мантиссу 	cmp	dh, 0		;проверим на повтор 	jne	num_err		;знак задан! Ошибка!  	mov	edx, 0100h	;помечаем, что знак задан и остался + 	jmp	sym_loop plus_order:			;знак в порядке 	cmp	bh, 2		;задан? 	je	num_err		;повтор! Ошибка! 	mov	bx, 0200h	;помечаем, что знак задан и остался + 	jmp	sym_loop  minus_sign:			;- 	cmp	bh, 0		;вводим порядок? 	jne	minus_order	 	cmp	dh, 0		;проверим на повтор 	jne	num_err 	mov	edx, 0101h	;помечаем, что знак задан и стал - 	jmp	sym_loop minus_order: 	cmp	bh, 2		;задан? 	je	num_err 	mov	bx, 0201h	;помечаем, что знак задан и он - 	jmp	sym_loop  point_sign:			;. 	cmp	bh, 0 	jne	num_err		;точка в порядке запрещена 	cmp	ch, 0		;проверим на повтор 	jne	num_err 	mov	ecx, 0101h	;помечаем, что точка задана 	fld1 	fidiv	c10num		;1/10 	fstp	numfloat	;зададим вес первой дробной цифры (0.1) 	jmp	sym_loop  order_sign:			;символ порядка (e или E) 	ftst			;проверим  на 0 	fstsw	ax		;флаги в ax 	sahf			;флаги в регистре флагов 	jz	num_err		;при задании порядка должна быть ненулевая мантисса 	cmp	bh, 0 	jne	num_err		;и только раз задано e(E) 	mov	bh, 1		;помечаем, что задан порядок 	jmp	sym_loop  set_order:			;строка обработана, учтем порядок 	cmp	bh, 0		;порядок есть? 	je	set_sign	;нет - на установку знака 	mov	cx, order	;порядок 	jcxz	set_sign	;порядок = 0 - ничего менять не надо 	cmp	bl, 0		;+ или - 	je	positive_loop negative_loop:			;- 	fidiv	c10num		;делим cx раз на 10 	loop	negative_loop		 	jmp	set_sign positive_loop:			;+ 	fimul	c10num		;умножаем cx раз на 10 	loop	positive_loop		 set_sign:			;учтем знак 	cmp	dl, 0		;+ или - 	je	str2float_ok	;+ выходим 	fchs			;меняем на - str2float_ok: 	clc			;все ок str2float_ret: 	ret 	endp  ;преобразование float из sp в строку по адресу pStr float2str	proc uses di, pStr:word local	dig:word, c10:word 	 	mov	c10, 10		;будем делить на 10 	mov	di, pStr	;здесь будем формировать строку 	ftst			;Проверяем число 	fstsw	ax		;флаги в ax 	sahf			;флаги в регистре флагов 	jnz	float2str_notZero	;не 0 	mov	ax, '0' 	;если 0, то рисуем 0 и выводим 	stosw 	jmp	float2str_Ret 	;на выход  float2str_notZero:		;не 0 	jnc	f2s_1		;проверим знак 	mov	al, '-' 	;для отрицательного выведем знак минус 	stosb 	fchs			;и меняем знак числа.  ; Пояснение далее пойдёт на примере.	; ST(0) ST(1) ST(2) ST(3) ... ; Отделим целую часть от дробной.	; 73.25 ... что-то не наше f2s_1: 	fld1				;  1	 73.25 ... 	fld	st(1)			; 73.25  1	 73.25 ... ; Остаток от деления на единицу даст дробную часть. 	fprem				;  0.25  1	 73.25 ... ; Если вычесть её из исходного числа, получится целая часть. 	fsub	st(2), st 		;  0.25  1	 73	 ... 	fxch	st(2)			; 73	 1	  0.25 ... ; Сначала поработаем с целой частью. Считать количество цифр будем в CX. 	xor	cx, cx ; Поделим целую часть на десять, f2s_2:	fidiv	c10			;  7.3	 1     0.25 ... 	fxch	st(1)			;  1     7.3   0.25 ... 	fld	st(1)			;  7.3   1     7.3  0.25 ... ; отделим дробную часть - очередную справа цифру целой части исходного числа,- 	fprem				;  0.3   1     7.3  0.25 ... ; от частного оставим только целую часть 	fsub	st(2), st 		;  0.3   1     7    0.25 ... ; и сохраним цифру 	fimul	c10			;  3     1     7    0.25 ... 	fistp	dig			;  1     7     0.25 ... ; считаем цифры 	inc	cx ; сохраняем в стеке. 	push	dig 	fxch	st(1)			;  7     1     0.25 ... ; Так будем повторять, пока от целой части не останется ноль. 	ftst 	fstsw	ax 	sahf 	jnz	f2s_2 ; Теперь выведем цифры целой части. f2s_3:	pop	ax ; Вытаскиваем очередную цифру, переводим её в символ и выводим. 	add	al, 30h 	stosb ; И так, пока не выведем все цифры. 	loop	f2s_3			;  0     1     0.25 ...  ; Итак, теперь возьмёмся за дробную часть, для начала проверив её существование. 	fstp	st(0)			;  1     0.25 ... 	fxch	st(1)			;  0.25  1    ... 	ftst 	fstsw	ax 	sahf 	jz	f2s_5			;дробной части нет - выходим ; Если она всё-таки ненулевая, выведем точку и 6 знаков после точки 	mov	al, '.'			;рисуем точку 	stosb 	mov	cx, 6			;6 знаков после запятой ; Помножим дробную часть на десять f2s_4:	fimul	c10			;  2.5   1    ... 	fxch	st(1)			;  1     2.5  ... 	fld	st(1)			;  2.5   1     2.5  ... ; отделим целую часть - очередную слева цифру дробной части исходного числа,- 	fprem				;  0.5   1     2.5  ... ; оставим от произведения лишь дробную часть 	fsub	st(2), st 		;  0.5   1     2    ... 	fxch	st(2)			;  2     1     0.5  ... ; сохраним полученную цифру во временной ячейке 	fistp	dig			;  1     0.5  ... ; и сразу выведем. 	mov	ax, dig 	add	al, 30h 	stosb ; Теперь, если остаток дробной части ненулевой 	fxch	st(1)			;  0.5   1    ... 	ftst 	fstsw	ax 	sahf ; и мы вывели менее cx цифр, продолжим 	loopnz	f2s_4			;  0     1    ... ; Итак, число выведено. Осталось убрать мусор из стека. f2s_5:	fstp	st(0)			;  1    ... 	fstp	st(0)			;  ... 	mov	byte ptr [di], 0	;закрываем строку float2str_ret: 	ret 	endp  	.data x	dd	0 y	dd	0 z	dd	0 a	dd	? b	dd	? ;константы c008	dd	0.08 c3	dd	3. c0005	dd	0.005 c7	dd	7. c5	dd	5. c00006	dd	0.00006  sAny	db	0dh,0ah,'Press any key',0 sEnterX	db	0dh,0ah,'Enter x: ',0 sEnterY	db	0dh,0ah,'Enter y: ',0 sEnterZ	db	0dh,0ah,'Enter z: ',0 sA	db	0dh,0ah,'a = ',0 sB	db	0dh,0ah,'b = ',0 sBuf	db	32 cnt	db	? string	db	32 dup (?) sNum	db	32 dup (?)  	end	start

Консультировал: Лысков Игорь Витальевич (Старший модератор)
Дата отправки: 25.06.2012, 02:39

5
нет комментария
-----
Дата оценки: 25.06.2012, 08:24

Рейтинг ответа:

НЕ одобряю +1 одобряю!


Оценить выпуск | Задать вопрос экспертам

главная страница  |  стать участником  |  получить консультацию
техническая поддержка  |  восстановить логин/пароль

Дорогой читатель!
Команда портала RFPRO.RU благодарит Вас за то, что Вы пользуетесь нашими услугами. Вы только что прочли очередной выпуск рассылки. Мы старались. Пожалуйста, оцените его. Если совет помог Вам, если Вам понравился ответ, Вы можете поблагодарить автора - для этого в каждом ответе есть специальные ссылки. Вы можете оставить отзыв о работе портале. Нам очень важно знать Ваше мнение. Вы можете поближе познакомиться с жизнью портала, посетив наш форум, почитав журнал, который издают наши эксперты. Если у Вас есть желание помочь людям, поделиться своими знаниями, Вы можете зарегистрироваться экспертом. Заходите - у нас интересно!
МЫ РАБОТАЕМ ДЛЯ ВАС!


 
 
Комментировать выпуск
     В избранное

Прошлые выпуски
RFpro.ru: Ассемблер? Это просто! Учимся программировать    24 июня 2012, 19:33
RFpro.ru: Ассемблер? Это просто! Учимся программировать    23 июня 2012, 15:32
RFpro.ru: Ассемблер? Это просто! Учимся программировать    22 июня 2012, 15:02

Все выпуски рассылки

26 июня 2012 отмечают:
Международный день борьбы с&nbsp;употреблением наркотиков и&nbsp;их&nbsp;незаконным оборотом
Международный день в&nbsp;поддержку жертв пыток
День работников прокуратуры Беларуси
День вооруженных сил Азербайджана
День памяти Сунтхона Пху

Именины: Акулина, Александр, Андрей, Анна, Антонина, Даниил, Дмитрий, Иван, Пелагея
 
 

Subscribe рекомендует
 
Компьютеры и интернет  →   рассылки   и   группы
  
Будущий Президент России
Группа тех,кто готов поддержать на Президентских выборах Макарова Сергея.
Темы: 41   Участники: 438
  Свободный микрофон
Вы готовы брать ответственность за каждую свою мысль, каждое своё слово и действие? Тогда, ДОБРО ПОЖАЛОВАТЬ в группу, в которой приветствуется: желание ...
Темы: 4086   Участники: 1530
  Учимся работать в компьютерных программах
Приветствуем Вас в группе "Учимся работать в компьютерных программах" ! Наша группа поможет каждому обучиться работе на компьютере и в Интернете . Начин...
Темы: 4209   Участники: 24609
 
 
 
Подписан адрес: admin10383.deep@blogger.com
Код этой рассылки: comp.prog.assembler
Архив рассылки
Отписаться:  На сайте  Почтой
Поддержка подписчиков
Убрать рекламу
Другие рассылки этой тематики
Другие рассылки этого автора
 
Рассылка производится: Subscribe.Ru / ЗАО «Интернет-Проекты» / О компании / Политика конфиденциальности

Комментариев нет:

Отправить комментарий