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

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


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

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

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

Boriss
Статус: Академик
Рейтинг: 2249
∙ повысить рейтинг »
_Ayl_
Статус: Практикант
Рейтинг: 1833
∙ повысить рейтинг »
vladisslav
Статус: 6-й класс
Рейтинг: 1237
∙ повысить рейтинг »

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

Номер выпуска:1335
Дата выхода:12.05.2010, 11:00
Администратор рассылки:Лысков Игорь Витальевич, Модератор
Подписчиков / экспертов:279 / 59
Вопросов / ответов:4 / 4
IRC-канал по теме:#assembler

Вопрос № 178235: Здравствуйте уважаемые эксперты! Нужно написать программу: Построение графика функции f(x)=cos(n*x+m*Pi), входные данные -- n и m, выходные -- график. Использовать TASM. Сделать в DOS. ...


Вопрос № 178239: Здравствуйте уважаемые эксперты! У меня возникло затруднение - надо написать программу на TASM которая объединяет слова, начинающиеся на один и тот же символ и дописывает его (объединенное слово) в конец строки и вывести их на экран. слова вводить...
Вопрос № 178248: Уважаемые эксперты, помогите пожалуйста написать программу: Составить программу сложения N (N<16) однобайтных чисел. Числа должны располагаться в памяти программ, начиная с адреса после кодов программы. Результат должен фиксироваться в ячейках...
Вопрос № 178252: Здравствуйте,помогите пожалуйста с программой!У меня в файле число!Нужно вывести его цифры в обратном порядке!Есть программа по выводу исходных данных из этого файла!Число 127!Спасибо!...

Вопрос № 178235:

Здравствуйте уважаемые эксперты! Нужно написать программу: Построение графика функции
f(x)=cos(n*x+m*Pi), входные данные -- n и m, выходные -- график.
Использовать TASM.
Сделать в DOS.

Отправлен: 06.05.2010, 17:06
Вопрос задал: rmka, Посетитель
Всего ответов: 1
Страница вопроса »


Отвечает Лысков Игорь Витальевич, Модератор :
Здравствуйте, rmka.
Вводим вещественные коэффициенты n и m, затем рисуем график
Сейчас сделано так, что 25 точек на экране (переменная coef) соответствуют единице.
Код:
;Построение графика функции f(x)=cos(n*x+m*Pi), 
;входные данные -- n и m, выходные -- график.

.model tiny, C ; модель памяти и порядок вызова параметров
.386 ; нужно для команды fcos
.code ; сегмент кода
.startup ; точка входа

;введем N и M
call GetNum, offset sN, offset NMax, offset N
call GetNum, offset sM, offset MMax, offset M

;преходим в графику
mov ax, 0013h ; vga 320x200x256
int 10h

mov ax, 0a000h
mov es, ax ; es - сегмент видео

call line, 20, 100, 300, 100, 8 ;ось абсцисс
call line, 160 , 20, 160, 180, 8 ;ось ординат
call Graph, 20, 300, offset fun, 0bh ;сам график
call PrFun, 3 ;напишем функцию

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

;выход в DOS
mov ax, 0003h ; назад в текстовый режим
int 10h

mov ax, 4c00h ; bye-bye
int 21h

;Вводим вещственное число
;параметры:
;pStr - адрес строки приглашения
;pMax - адрес строки для ввода по функции 0ah
;pNum - адрес, куда пишем вещественное число
GetNum proc pStr:word, pMax:word, pNum:word
local i:word ;переменная для работы с сопроцессором

mov dx, pStr ;приглашение
mov ah, 9
int 21h

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

lea si, [si+2] ;на адрес введенной строки
xor cx, cx ;ch=0 - признак целой части, ch=1 - дробная часть
xor di, di ;число (без учета точки)
GN_loop:
lodsb ;очередной символ
cmp al, 0dh
je GN_Form ;прошли по всей строке
cmp al, '.'
je GN_Point ;точка
cmp al, '0'
jb GN_loop ;допускаем только цифры
cmp al, '9'
ja GN_loop

cmp ch, 0
je GN_dig ;целая часть - на формирование числа
inc cl ;дробная - сначала посчитаем число цифр дробной части
GN_dig:
push ax ;умножаем старшие разряды на 10 и добавляем новый
mov ax, 10
mul di
mov di, ax
pop ax
and ax, 0fh
add di, ax
jmp GN_loop
GN_Point: ;точка
cmp ch, 1
je GN_loop ;если повтор точки, то игнорируем (на всякий случай)
mov ch, 1 ;помечаем
jmp GN_loop
GN_Form: ;учтем дробную часть
mov i, di ;запишем число в переменную
fild i ;загрузим в сопроцессор
mov ch, 0 ;сформируем счетчик во всем регистре cx
jcxz GN_Save ;если дробной части нет, то на сохранение
mov i, 10 ;константа для деления
GN_Div:
fild i ;cx раз делим на 10
fdiv
loop GN_Div
GN_Save:
mov di, pNum ;адрес, куда сохраняем вещес твенное число
fstp dword ptr [di] ;сохраняем результат в виде float
ret
GetNum endp

;считает ax=y=f(x) в экранных координатах
;параметр: x - экранная координата по горизонтали
fun proc x:word
mov ax, x ;сделаем из x знаковое число
sub ax, 160 ;x=160 - центр экрана считаем нулем
mov x, ax ;сохраним в переменной для загрузки в сопроцессор
fild x ;грузим в сопроцессор
fdiv coef ;делим на коэффициент coef точек = 1
fmul n ;x * n
fldpi ;пи
fmul m ;пи * m
faddp ;x * n + пи * m
fcos ;cos(x * n + пи * m)
fmul coef ;масштабируем: умножаем на коэффициент coef:1
fistp x ;преобразуем в целое
mov ax, 100 ;100 - центр экрана по вертикали
sub ax, x ;ax - экранная координата по вертикали
ret
fun endp

;рисует график, последовательно соединяя точки отрезками
;параметры:
;xmin - левая экранная координата графика
;xmax - правая экранная координата графика
;pFun - адрес фун кции, вычисляющей экранную координату по вертикали
;col - цвет линий
Graph proc xmin:word, xmax:word, pFun:word, col:word
Graph_ loop: ;цикл рисования отрезков
mov ax, pFun ;адрес функции
call ax, xmin ;считаем y первой точки
mov cx, ax ;сохраним в cx

mov ax, xmin ;найдем x соседней справа точки
inc ax
mov si, ax ;сохраним в sі
cmp ax, xmax ;проверим, дошли и до правого края
ja Graph_ret

mov ax, pFun ;адрес функции
call ax, si ;ax = y второй точки

;рисуем линию (xmin, cx)-(si,ax) цветом col
call line, xmin, cx, si, ax, col
mov xmin, si ;готовим xmin для следующего шага
jmp Graph_loop
Graph_ret:
ret
Graph endp

;рисуем линию (x1,y1)-(x2,y2) цветом color
Line proc uses di bx, x1:word, y1:word, x2:word, y2:word, color:byte
local i:word, \ ;для работы со сопроцессором
delta_x:word, \ ;длина проекции на ось абсцисс
delta_y:word, \ ;длина проекции на ось ординат
incx:word, \ ;приращение по X
incy:word ;приращение по Y

;определим длину проекции на ось абсцисс и шаг по оси X
mov ax, x2
sub ax, x1 ;ax=x2-x1;

;определим шаг по X (+1 если вперед, -1 если назад, 0 если не меняется)
mov incx, 0 ;пусть incx=0
test ax, ax ;ax=delta_x
jz set_delta_x ;не меняется
jg set_x_1 ;вперед?
dec incx ;назад, значит incx=-1
neg ax ;найдем ax=abs(delta_x)
jmp set_delta_x ;на сохранение
set_x_1:
inc incx ;вперед, значит incx=1;
set_delta_x:
mov delta_x, ax ;delta_x = abs(x2-x1)

;определим длину проекции на ось ординат и шаг по оси Y
mov ax, y2
sub ax, y1 ;ax=y2-y1;

;определим шаг по Y (+1 если вперед, -1 если назад, 0 если не меняется)
mov incy, 0 ;пусть incy=0
test ax, ax ;ax=delta_y
jz set_delta_y ;не меняется
jg set_y_1 ;вперед?
dec incy ;назад, значит incy=-1
neg ax ;найдем ax==abs(delta_y)
jmp set_delta_y ;на сохранение
set_y_1:
inc incy ;вперед, значит incy=1;
set_delta_y:
mov delta_y, ax ;delta_y=abs(y2-y1)

;определим большее из проекц ий как основное напрвление
cmp ax, delta_x ;ax=delta_y
jge from_y ;y будет основным
cmp delta_x, 0 ;проверим, чтобы не было delta_x=0 (для точки),
jz Line_ret ; иначе будет деление на 0
;delta_x>delta_y && delta_x!=0
;основное направление - по оси X
fild delta_y
fidiv delta_x ;st=k=(float)(delta_y/delta_x)

;for (int i=0;i<delta_x;i++)
xor cx, cx ;cx=i
jmp cmp_i_x ;на проверку i<delta_x
x_loop: ;тело цикла
mov i, cx ;запишем переменную цикла в память (для сопроцессора)
fld st ;st=st(1)=k
fimul i ;st=k*i
fimul incy ;st=incy*k*i
call floor ;округлим до целого в большую сторону
fistp i ;сохраним в переменной
mov ax, i ;относительный номер строки на экране
add ax, y1 ;добавим до ординаты начальной точки
mov dx, 320 ;получим индекс начала строки экрана в сегменте экрана
imul dx ; для этого умножим на длину в байтах одной стоки
mov bx, ax ;сохраним bx=y=(y1+floor( incy*k*i))*320
;посчитаем X
mov ax, incx ;X меняется ровно на шаг приращения,
imul cx ; умноженному на индекс точки
add ax, x1 ;добавим абциссу начальной точки ax=x=x1+incx*i

add ax, bx ;сложим с индексом начала строки
mov di, ax ;будем адресовать через di

mov al, color ;цвет точки
mov es:[di], al ;рисуем!

inc cx ;на следующую точку
cmp_i_x:
cmp cx, delta_x ;дошли до конца?
jl x_loop
jmp Line_ret ;на выход

from_y: ;вдоль оси Y
fild delta_x
fidiv delta_y ;st=k=(float)(delta_x/delta_y)

;for (int i=0;i<delta_y;i++)
xor cx, cx ;cx=i
jmp cmp_i_y ;на проверку i<delta_y
y_loop: ;тело цикла
mov ax, incy ;Y меняется ровно на шаг приращения,
imul cx ; умноженному на индекс точки
add ax, y1 ;добавим абциссу начальной точки ax=y=y1+incy*i
mov dx, 320 ;получим индекс начала строки экрана в сегменте экрана
imul dx ; для этого умножим на длину в б айтах одной стоки
mov bx, ax ;сохраним bx=y=(y1+incy*i)*320
;посчитаем X
mov i, cx ;запишем переменную цикла в память ( для сопроцессора)
fld st ;st=st(1)=k
fimul i ;st=k*i
fimul incx ;st=incx*k*i
call floor ;округлим до целого в большую сторону
fistp i ;сохраним в переменной
mov ax, i ;относительный номер строки на экране
add ax, x1 ;ax=x=x1+floor(incx*k*i)

add ax, bx ;сложим с индексом начала строки
mov di, ax ;будем адресовать через di

mov al, color ;цвет точки
mov es:[di], al ;рисуем!

inc cx ;на следующую точку
cmp_i_y:
cmp cx, delta_y ;дошли до конца?
jl y_loop
Line_ret:
fistp i ;удалим из сопроцессора k
ret
Line endp

;округление до целого в большую сторону
;округление по умолчанию, до ближайщего, не устраивает
floor proc
local CtrlWordOld:word, CtrlWordNew:word
fstcw CtrlWordOld ;сохраним управляющее слово
fclex ;сбросим исключения
mov CtrlWordNew, 0763h ;установим необходимое значение управляющего слова
fldcw CtrlWordNew ;загружаем управляющее слово
fr ndint ;округляем st до целого
fclex ;сбросим исключения
fldcw CtrlWordOld ;восстановим старое управляющее слово
ret
floor endp

;выводим на экран f(x)=cos(n*x+m*Pi)
;параметр textcolor - цвет текста
PrFun proc textcolor:word
mov bx, textcolor ;цвет
lea si, Pr1 ;первая часть текста
call PrText
lea si, NText ;N в виде строки
call PrText
lea si, Pr2 ;вторая часть текста
call PrText
lea si, MText ;M в виде строки
call PrText
lea si, Pr3 ;третья часть текста
call PrText
ret
PrFun endp

;выводим строку по адресу [si], строка должна заканчиваться 0dh
PrText proc
lodsb
cmp al, 0dh
je PrRet
mov ah, 0eh
int 10h
jmp PrText
PrRet:
ret
PrText endp

.data
n dd 0 ;исходные коэффициенты
m dd 0
coef dd 25. ;коэффициент для масштабирования на экране
sN db 'N= $'
sM db 0dh,0ah,'M= $'
Pr1 db 'f(x)=cos(',0dh< br>Pr2 db '*x+',0dh
Pr3 db '*Pi)',0dh
NMax db 6
db 0
NText db 7 dup (0)
MMax db 6
db 0
MText db 7 dup (0)
END

-----
Удачи!

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

Оценка ответа: 5

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

  • Вопрос № 178239:

    Здравствуйте уважаемые эксперты!
    У меня возникло затруднение - надо написать программу на TASM которая объединяет слова, начинающиеся на один и тот же символ и дописывает его (объединенное слово) в конец строки и вывести их на экран. слова вводить с клавиатуры.
    вот пример:
    waba wordos absen ; вводим исходную строку
    waba wordos absen wabawordos ; то что должно получиться
    дополнительные сведения: работа на TASM - 92 для процессора 8086 под дос (командная строка в windows xp)
    предназначена для учебы.
    и пожалуйста напишите программу наиболее простым способом (понятным для студента ) и прокомментируйте строчки я в ассемблере не очень силен
    P.S. а можно будет задавать вопросы по пришлённому ответу если в нем что то неясно будет ?
    Большое спасибо!

    Отправлен: 06.05.2010, 17:56
    Вопрос задал: Timmy, Посетитель
    Всего ответов: 1
    Страница вопроса »


    Отвечает amnick, 10-й класс :
    Здравствуйте, Timmy.

    В приложении приведен мой вариант решения Вашей задачи. Схема такая: читаем строку с клавиатуры в буфер, разбиваем ее на слова. Слова могут быть разделены одним или несколькими символами, перечисленными в массиве delimiters, так что Вы легко можете изменить разделители. Для каждого слова сохраняется его длина и указатель на начало. Предполагается, что слов не более 20, при превышении выводится сообщение и программа прекращает работу.
    После заполнения массивов программа в цикле проверяет первые буквы слов на совпадение и дополняет входной буфер объединенными словами. В конце выводится результат.

    Программа должна компилироваться в COM-файл.

    Если есть вопросы, то обращайтесь в мини-форум, постараюсь помочь.

    Успехов!

    Приложение:

    Ответ отправил: amnick, 10-й класс
    Ответ отправлен: 06.05.2010, 23:11
    Номер ответа: 261244

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

  • Вопрос № 178248:

    Уважаемые эксперты, помогите пожалуйста написать программу:
    Составить программу сложения N (N<16) однобайтных чисел. Числа должны располагаться в памяти программ, начиная с адреса после кодов программы. Результат должен фиксироваться в ячейках внешней памяти, начиная с адреса 0000H.
    Заранее благодарен.

    Отправлен: 06.05.2010, 23:01
    Вопрос задал: diavolic89, Посетитель
    Всего ответов: 1
    Страница вопроса »


    Отвечает Лысков Игорь Витальевич, Модератор :
    Здравствуйте, diavolic89.
    Ваша программа:
    Код:
    ;Программа сложения N (N<16) однобайтных чисел. 
    ;Числа располагаются в памяти программ, начиная с адреса после кодов программы.
    ;Результат фиксируется в ячейках внешней памяти, начиная с адреса 0000H.
    sumaddr equ 0 ;адрес внешней памяти, куда запишем результат
    sumlow equ 8 ;переменные во внутренней памяти для суммы, младший байт
    sumhigh equ 9 ;старший байт
    stack eqy 60h ;вершина стека

    mov sp, #stack ;стек

    mov dptr, #array ;адрес массива в программной памяти
    mov r2, #0 ;индекс в массиве
    mov r3, #N ;количество элементов массива
    mov sumlow, #0 ;пусть сумма пока равна 0
    mov sumhigh, #0
    loop: ;цикл по складыванию элементов массива
    mov a, r2 ;индекс очередного элемента
    inc r2 ;для следующего
    movc a, @a+dptr ;читаем в аккум из программной памяти байт по адресу [a]+[dptr]
    add a, sumlow ;складываем с младшим
    mov sumlow, a ;сохраняем младший байт
    mov a, #0 ;надо учесть перенос!
    addc a, sumhigh ;для этого складываем старший байт с 0 и с переносом (FC)
    mov sumhigh, a ;сохраняем старший байт
    djnz r3, loop ;r3=r3-1; циклим, пока r3!=0

    mov dptr, #sumaddr ;пишем найденную сумму во внешнюю память
    mov a, sumlow ;сначала младший байт
    movx @dptr, a ;пишем a->[dptr]
    inc dptr
    mov a, sumhigh ;следом старший байт суммы
    movx @dptr, a ;пишем a->[dptr]

    jmp $ ;задача решена, организовываем бесконечный цикл:
    ; крутимся на одном месте

    array: ;данные
    db 3,6,4,8,2,0,3,7,1,6,5,3,8,2,23h,10h
    N equ $-array ;длина массива

    end
    Обратите внимание, что сумма в двух байтах
    -----
    Удачи!

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

    Оценка ответа: 5

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

  • Вопрос № 178252:

    Здравствуйте,помогите пожалуйста с программой!У меня в файле число!Нужно вывести его цифры в обратном порядке!Есть программа по выводу исходных данных из этого файла!Число 127!Спасибо!

    Отправлен: 06.05.2010, 23:31
    Вопрос задал: Калинина Е.А., Посетитель
    Всего ответов: 1
    Страница вопроса »


    Отвечает Лысков Игорь Витальевич, Модератор :
    Здравствуйте, Калинина Е.А..
    Вы написали программу в формате Debug-а.
    Я решил написать в формате TASM-а. Так же нагляднее :)
    Кроме того, добавил обработку ошибок...
    Если что непонятно, спрашивайте.
    Код:

    .model tiny
    .code
    .startup

    jmp continue

    FName db 'c:\file1.txt',0
    Num db 'dan$'
    ErrNotFound db 'File not found$'
    ErrRead db 'Read error$'

    continue:
    mov ax, 3d00h
    mov dx, offset FName
    int 21h
    jc ErrorNotFound ;файл не найден
    mov bx, ax
    mov ah, 3fh
    mov cx, 3
    mov dx, offset Num
    int 21h
    jc ErrorRead ;ошибка чтения
    mov ah, 3eh
    int 21h

    mov al, Num ;меняем местами 1 и 3 байты :)
    xchg al, Num+2
    mov Num, al
    mov ah,9 ;dx указывает на число
    int 21h

    ret

    ErrorRead:
    mov dx, offset ErrRead
    jmp PrintError
    ErrorNotFound:
    mov dx, offset ErrNotFound
    PrintError:
    mov ah, 9
    int 21h
    ret

    end

    -----
    Удачи!

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

    Оценка ответа: 5
    Комментарий к оценке:
    Спасибо огромное!!!

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

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

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

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

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

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

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

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


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

    В избранное