Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

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


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

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

Чемпионы рейтинга экспертов в этой рассылке

Boriss
Статус: Академик
Рейтинг: 1934
∙ повысить рейтинг »
_Ayl_
Статус: Практикант
Рейтинг: 1835
∙ повысить рейтинг »
vladisslav
Статус: 5-й класс
Рейтинг: 1117
∙ повысить рейтинг »

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

Номер выпуска:1319
Дата выхода:05.04.2010, 13:00
Администратор рассылки:Лысков Игорь Витальевич, Модератор
Подписчиков / экспертов:416 / 71
Вопросов / ответов:1 / 1
IRC-канал по теме:#assembler

Вопрос № 177575: Доброго времени суток дорогие эксперты помогите решить две задачки, с которыми я не могу справится изза отсутствия опытности. 1) требуется написать программу для вычисления двух выражений с использованием макросов и процедур. Каж...



Вопрос № 177575:

Доброго времени суток дорогие эксперты

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

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, 12:43
Вопрос задал: Юдин Евгений Сергеевич, 1-й класс
Всего ответов: 1
Страница вопроса »


Отвечает Лысков Игорь Витальевич, Модератор :
Здравствуйте, Юдин Евгений Сергеевич.
Вот Вам первая программа.
Все данные задаются в коде. Ничто не вводится/не выводится.
Цель данной программы - работа с макро, разными сегментами и с сопроцессором
Код:

.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 и получаем требуемые простые числа по методу "решета Эратосфена&q uot;
Код:

.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< br> 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 Pr intDigit ;выведем 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

-----
Удачи!

Ответ отправил: Лысков Игорь Витальевич, Модератор
Ответ отправлен: 02.04.2010, 10:50
Номер ответа: 260530
Украина, Кировоград
Тел.: +380957525051
ICQ # 234137952
Mail.ru-агент: igorlyskov@mail.ru
Абонент Skype: igorlyskov

Вам помог ответ? Пожалуйста, поблагодарите эксперта за это!
Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 260530 на номер 1151 (Россия) | Еще номера »
  • Отправить WebMoney:

  • Оценить выпуск »
    Нам очень важно Ваше мнение об этом выпуске рассылки!

    Задать вопрос экспертам этой рассылки »

    Скажите "спасибо" эксперту, который помог Вам!

    Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА
    на короткий номер 1151 (Россия)

    Номер ответа и конкретный текст СМС указан внизу каждого ответа.

    Полный список номеров »

    * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов)
    ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
    *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.


    © 2001-2010, Портал RFpro.ru, Россия
    Авторское право: ООО "Мастер-Эксперт Про"
    Автор: Калашников О.А. | Программирование: Гладенюк А.Г.
    Хостинг: Компания "Московский хостер"
    Версия системы: 2010.6.14 от 03.03.2010

    В избранное