Консультация № 177575
31.03.2010, 12:43
45.00 руб.
0 15 1
Доброго времени суток дорогие эксперты

помогите решить две задачки, с которыми я не могу справится изза отсутствия опытности.

1) требуется написать программу для вычисления двух выражений с использованием макросов и процедур. Каждую переменную(x,y,z) описывать в отдельных сегментах данных:

a=(0.08cos^2(3x)-e^z)/((корень 5 степени из(log^2(по основанию 3 числа y)-z))+7z)

b=(корень 5 степени из(log^2(по основанию 3 числа y)-z)-5y+0.00006

2)Построить массив всех простых чисел, не превышающих заданное число N. Результаты вы-вести на экран.
Ввести с клавиатуры двоичное число в виде последовательности K двоичных цифр (k<8 ) и выдать на экран символ, которому соответствует эта последовательность.

заранее большое спасибо дорогие эксперты!)))

Обсуждение

Неизвестный
31.03.2010, 13:24
общий
Но отсутствие опыта не должно было помешать Вам прочитать, как правильно задавать вопросы сюда
Все равно придется Вам уточнить все это
Неизвестный
31.03.2010, 13:31
общий
я уточнил все.....только что теперь? изза этого никто не рассмотрит вопросы?
Неизвестный
31.03.2010, 13:33
общий
к 2 задаче есть дополнение: При решении задачи в 1 предложении использовать функции MS DOS, во втором предложении – функции BIOS.
Неизвестный
31.03.2010, 13:47
общий
И это все, что можете уточнить?
"Там" предлагается уточнить вот что?
1) Какой процессор используется. Если х86-совместимый, то можно не указывать. За исключением случая, когда необходимы специальные возможности (например, MMX, 3D-NOW!, SSE, SSE2, ...);
2) Какая платформа (для х86-совместимых: ДОС/Windows/*nix);
3) Какой ассемблер предпочтителен (TASM, MASM, NASM, FASM, WASM, ...);
4) Размер переменных (байт, слово, двойное слово), с которыми должна работать программа, а также являются они числами со знаком или без знака.
5) Вычисления производить в сопроцессоре?

Это все нужно для того, чтобы НАМ меньше СВОЕГО времени тратить
Неизвестный
31.03.2010, 13:55
общий
хорошо извините упустил....
1)процессор intel core 2 solo CPU U3500
2)window vista home premium 32х разрядная
3)Turbo Assembler Version 4.1 в папке asm находится фаил TASM поэтому думаю он предпочтителен
4)числа могут быть как знаковыми так и без(ограничений тут нет) размер операндов тоже не так важен
5)да вычисления производить в сопроцессоре
спасибо за ваше внимание
давно
Посетитель
7438
7205
31.03.2010, 16:35
общий
Юдин Евгений Сергеевич:
Хм, у Вас не 2, а 3 задачи...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
31.03.2010, 22:12
общий
Да, и еще: ввод-вывод нужен? Предупреждаю, что при использовании TASM возни будет много
давно
Посетитель
7438
7205
02.04.2010, 10:50
общий
это ответ
Здравствуйте, Юдин Евгений Сергеевич.
Вот Вам первая программа.
Все данные задаются в коде. Ничто не вводится/не выводится.
Цель данной программы - работа с макро, разными сегментами и с сопроцессором
Код:

.386 ;необходимо для команды fcos
sseg segment stack "stack"
db 1024 dup (0)
sseg ends

dsegX segment use16 para public 'data'
x dd 1.5
dsegX ends

dsegY segment use16 para public 'data'
y dd 5.6
dsegY ends

dsegZ segment use16 para public 'data'
z dd 1.1
dsegZ ends

dseg segment use16 para public 'data'
a dd ?
b dd ?
;константы
c8 dd 0.08
c3 dd 3.
c5 dd 5.
c6 dd 0.00006
c7 dd 7.
dseg ends

;в st должно находиться xlog[2]y
POWER MACRO
fld st ;x*log[2]e->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 ;exp = 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-z)1/5
CALC_YZ MACRO yoff,zoff
les bx,yoff ;address y
fld dword ptr es:[bx] ;y->st
LOG3 ;st=log[3]y
fld st ;st=st(1)
fmulp ;st=log[3]y^2
les bx,zoff ;address z
fsub dword ptr es:[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

cseg segment para use16 public 'code'
assume cs:cseg, ss:sseg, ds:dseg
start:
mov ax,sseg
mov ss,ax
mov ax,dseg
mov ds,ax

push dsegX ;в стек длинные адреса x
push offset x
push dsegY ;y
push offset y
push dsegZ ;z
push offset z
call calc_a ;получаем в st ответ
fstp a ; и сохраняем его в переменной

push dsegY ;y
push offset y
push dsegZ ;z
push offset z
call calc_b ;получаем в st ответ
fstp b ; и сохраняем его в переменной

mov ax,3c00h
int 21h

par_z equ [bp+4] ;для адресации в стеке
par_y equ [bp+8]
par_x equ [bp+12]

calc_a proc
push bp
mov bp,sp

les bx, dword ptr par_x ;длинный указатель на x
fld dword ptr es:[bx] ;st = x
fmul c3 ;st = 3x
fcos ;st = cos(3x)
fld st ;st = st(1)
fmul ;st = cos(3x)^2
fmul c8 ;st = 0.08 * cos(3x)^2
les bx, dword ptr par_z ;длинный указатель на z
fld dword ptr es:[bx] ;st = z
EXP ;st = exp(z)
fsubp ;st = 0.08 * cos(3x)^2 - exp(z)

CALC_YZ par_y, par_z ;st = (log[3]y-z)1/5
les bx, dword ptr par_z ;длинный указатель на z
fld dword ptr es:[bx] ;st = z
fmul c7 ;st = 7z
faddp ;st = (log[3]y-z)1/5 + 7z

fdivp ;st = st(1) / st = a

pop bp
ret 12
calc_a endp

calc_b proc
push bp
mov bp,sp

CALC_YZ par_y, par_z ;st = (log[3]y-z)1/5
les bx, dword ptr par_y ;длинный указатель на y
fld dword ptr es:[bx] ;st = y
fmul c5 ;st = 5y
fsubp ;st = (log[3]y-z)1/5 - 5y
fadd c6 ;st = (log[3]y-z)1/5 - 5y + 0.00006

pop bp
ret 12
calc_b endp

cseg ends
end start
Вот вторая программа.
Вводим число N<= 32000 и получаем требуемые простые числа по методу "решета Эратосфена"
Код:

.286

cseg segment para public 'code'
assume cs:cseg, ds:dseg, es:dseg
start:
mov ax, dseg
mov ds, ax
mov es, ax

;будем хранить "решето Эратосфена" в стеке, поэтому выделим
;достаточно места для данных (максимально 32000 значений)
;сам сегмент будет размещен в конце, за сегментом данных
;изначально sp = 0
sub sp, 32000*2 ;максимум 32000 слов
mov bp, sp ;bp - начало массива данных

repeat: ;если ошибка, то повторим запрос максимального числа
call GetMax ;вводим макс число
jnc num_ok ;ошибки нет
jnz pr_err_max ;ошибка - переполнение, значение числа > 65536
;ошибка - не число
lea dx, ErrorNumMessage
mov ah, 9
int 21h
jmp repeat ;на повтор
num_ok:
jz exit ;пустая строка - на выход
cmp ax, 32000 ;проверим, чтобы было <= 32000
jbe max_ok ;с макс числом все в порядке
pr_err_max: ;число > 32000
lea dx, ErrorMaxMessage
mov ah, 9
int 21h
jmp repeat ;на повтор

max_ok:
mov num, ax ;сохраним

call Eratosphen ;строим массив простых чисел ("решето Эратосфена")

mov ah, 9
lea dx, simples
int 21h ;выведем строку "Simples: "

mov cx, num ;максимальное число
dec cx ;учтем, что всего 0-num, т.е. num+1 штук,
;но храним на 2 меньше, т.е. всего получается num-1 штук
xor si, si ;индекс
SimpleShow:
mov ax, [si+bp] ;очередное число
test ax, ax ;проверим, простое?
jz SimpleNext ;0 - составное
call outNumber ;простое выводим
SimpleNext:
add si, 2 ;на следующее число
loop SimpleShow

exit:
mov ax,4c00h ;выход
int 21h

GetMax proc ;вводим максимальное число с проверкой на корректность
lea dx, prompt
mov ah, 9
int 21h ;подсказка

lea dx, max
mov ah, 0ah
int 21h ;вводим строку

;преобразуем строку в число
xor di, di ;наше число
lea si, string ;адрес строки
GM_loop:
lodsb ;очередной байт
cmp al, 0dh ;проверим на последний 0dh
je GM_end ;дошли до конца
cmp al, '0' ;проверим на цифру
jb GM_error
cmp al, '9'
ja GM_error
push ax ;сохраним очередной разряд
mov ax, 10 ;сдвинем предыдущие на 1 десятичный разряд
mul di
pop cx ;восстановим текущую цифру
test dx, dx ;проверим на переполнение, т.е.число стало > 65536
jnz GM_max_error ;на ошибку переполнения
and cx, 000fh ;'0'-'9' -> 0-9
add ax, cx ;добавляем текущий разряд
mov di, ax ;и сохраним промежуточный результат
jmp GM_loop ;по всем цифрам
GM_end:
mov ax, di ;результат
test ax, ax ;проверим на пустую строку (для 0 флаг Z будет установлен)
clc ;ок
ret
GM_error: ;не число!
xor ax, ax ;флаг Z установлен
stc ;флаг C установлен
ret
GM_max_error: ;переполнение!
or ax, 1 ;флаг Z сброшен
stc ;флаг C установлен
ret
GetMax endp

Eratosphen proc ;построение "решета Эратосфена"
;заполним массив числами 2...max
xor si, si ;индекс в массиве
mov cx, num ;максимальное число
mov ax, 2 ;начнем с 2
sub cx, ax ;на 2 меньше (0 и 1)
shl cx, 1 ;cx - максимальное значение индекса
store:
mov [si+bp], ax ;сохраним
inc ax ;следующее
inc si ;индекс для следующего
inc si
cmp si, cx ;дошли до конца?
jbe store
;собственно построение "решета Эратосфена"
;будем заменять нулями составные числа
xor si, si ;индекс
ErLoop:
cmp si, cx ;сравним с максимальным значением
ja ErRet
mov ax, [si+bp] ;берем очередное число
test ax, ax
jz ErNext ;непростое обходим
mov di, si ;текущий адрес
shl ax, 1 ;адресуем слова
ErClear:
add di, ax ;добавляем значение простого
cmp di, cx ;проверим с максимальным
ja ErNext
mov word ptr [di+bp], 0 ;и отсеиваем составные (даже если уже было помечено)
jmp ErClear
ErNext:
inc si ;на следующее число
inc si
jmp ErLoop
ErRet:
ret ;составные стали нулями!
Eratosphen endp

outNumber proc ;вывод десятичного числа в виде строки, в конце один пробел
push cx ;сохраним счетчик цикла (при выводе массива)
mov bx, 10 ;десятичная система
xor cx, cx ;счетчик цифр в числе

isDiv: xor dx, dx ;делим число на 10
div bx
push dx ;запоминаем в стеке остаток от деления
inc cx ;считаем количество запоминаемых символов
or ax, ax ;продолжаем пока АХ не равно 0
jnz isDiv

isOutNum: ;выводим из стека цифры в нужном порядке
pop ax
or al, 30h ;переводим цифру в символ
;выводим в режиме телетайпа
;эта функция аналогична mov ah,02 - int 21h
;только места меньше занимает
int 29h
;повторяем вывод в цикле
loop isOutNum

mov al, 20h ;разделительный пробел
int 29h
pop cx ;восстановим счетчик
ret
OutNumber endp

cseg ends

dseg segment para public 'data'
prompt db 'Enter max number: $'
simples db 0ah,0dh,'Simples: $'
ErrorNumMessage db 0ah,0dh,'Not number! Repeat$'
ErrorMaxMessage db 0ah,0dh,'Number must be <= 32000! Repeat$'
;буфер для ввода строки
max db 6 ;максимально возможная длина (+1 для 0dh)
count db 0 ;реальная длина
string db 6 dup (?);сама строка
num dw 0 ;введенное число
dseg ends

end start ;конец программы
И третья программа...
Вывод осуществляем при помощи функции 0eh прерывания 10h BIOS, ввод с клавиатуры - с помощью прерывания 16h BIOS
Код:

.286

cseg segment para public 'code'
assume cs:cseg, ds:dseg
start:
mov ax, dseg
mov ds, ax

mov bh, 0 ;будем выводить в нулевую страницу,
;bh не меняется, поэтому зададим сразу
lea si, prompt
call print ;выведем приглашение на ввод строки бит

mov cx, 8 ;максимум 8 бит
mov dl, 0 ;здесь будет введенный байт

digits_loop: ;цикл ввода строки бит
mov ah, 0 ;ждем символ
int 16h
cmp al, 0dh ;по Enter-у выходим из ввода
je output
cmp al, '0' ;проверим на '0' и '1'
je num_ok
cmp al, '1'
jne digits_loop ;ждем только '0' и '1'
num_ok:
mov ah, 0eh ;выведем на экран
int 10h

rcr al, 1 ;вдвинем младший разряд (0 или 1) в С
rcl dl, 1 ;вдвинем С в наш байт!
loop digits_loop ;по всем 8 битам

output: ;выведем результат
;hex значение для красоты окружим 0 и h :)
;а символ окружим кавычками

;сначала выведем в виде hex-величины
lea si, resultHex ;строка "hex: "
call print

mov al, dl ;наш байт
call PrintHex ;выведем hex

lea si, result ;строка "String: "
call print

mov al, dl ;выведем байт
int 10h
mov al, '''' ;выведем кавычку
int 10h

lea si, press ;выведем "Press any key"
call print

mov ah, 0 ;ждем нажатия на клавишу
int 16h

mov ax, 4c00h ;выход
int 21h

;вывод строки средствами BIOS
;функция 0eh - вывод телетайпом в текущей позиции,
;требует в bh номер страницы и в al - символ
print proc
mov ah, 0eh ;функция BIOS для вывода
print_loop:
lodsb ;очереднй символ
test al, al ;строка заканчивается нулем
jz print_ret
int 10h ;сервис видео
jmp print_loop
print_ret:
ret
print endp

;вывод в виде hex-величины
PrintHex proc
push ax ;сохраним байт (нам еще будет нужен младший полубайт)
shr al, 4 ;старший полубайт
call PrintDigit ;выведем hex-цифру
pop ax ;восстановим
and al,0fh ;младший полубайт
PrintDigit:
add al, 90h ;0-f -> '0'-'f'
daa
adc al, 040h
daa
mov ah, 0eh
int 10h ;выведем
ret
PrintHex endp

cseg ends

dseg segment para public 'data'
prompt db 'Enter binary string: ',0
resultHex db 0dh,0ah,'Hex: 0',0
result db 'h, Symbol: ''',0
press db 0dh,0ah,'Press any key for exit',0
dseg ends

end start
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
02.04.2010, 10:56
общий
Юдин Евгений Сергеевич:
Пока посмотрите первую программу.
Чуть позже сделаю остальные. (В пункте 2 по сути две несвязанные между собой задачи )
Или, может, объединить в одной?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
02.04.2010, 13:14
общий
Юдин Евгений Сергеевич:
Добавил нахождение простых чисел .
Программа по методу "решета Эратосфена" строит разряженный массив простых чисел.
При желании можете скопировать в другое место только простые числа.
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
02.04.2010, 14:01
общий
boriss ввода вывода не надо
Лысков Игорь Витальевич спасибо что рассматриваете...в пункте 2 - 2 задачи.......они не связаны и требуют каждый программу для себя
давно
Посетитель
7438
7205
02.04.2010, 14:09
общий
Юдин Евгений Сергеевич:
Сделано
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
02.04.2010, 14:14
общий
спасибо дорогие эксперты
давно
Посетитель
7438
7205
02.04.2010, 14:17
общий
Юдин Евгений Сергеевич:
В третьей программе добавил еще вывод в виде hex-числа... Без этого как-то некрасиво смотрится...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
02.04.2010, 14:24
общий
спасибо... действительно!=)
Форма ответа