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

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


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

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

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

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

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

Номер выпуска:1356
Дата выхода:10.06.2010, 12:30
Администратор рассылки:Лысков Игорь Витальевич, Модератор
Подписчиков / экспертов:238 / 62
Вопросов / ответов:4 / 5
IRC-канал по теме:#assembler

Вопрос № 178508: Доброго времени суток, уважаемые эксперты! Прошу помочь с такой задачей: необходима программа калькулятора, которая выполняет сложение, вычитание, умножение, деление, возведение в степень, извлечение корня. (можно в форме диалога). DOS, TASM.Заранее ...


Вопрос № 178856: Здравствуйте, уважаемые эксперты. Помогите разобраться с реализацией алгоритма Брезенхейма в приведённой ниже процедуре. В Википедии алгоритм описан как увеличение X, при увеличении значения ошибки на величину наклона S, где S = Y1 - Y0/X1 - X0, т.е....
Вопрос № 178859: Здравствуйте уважаемые эксперты! У меня такой вопрос, точне нужна помощь. Задача такая вообщем, нужно реализовать на ассемблере программу, которая с клавиатуры 16-ричное двухзначное (восьмиразрядное) число, переводит его в 10-чное и 2-чное, а резул...
Вопрос № 178862: Уважаемые эксперты! Помогите пожалуйста разработать программу на языке ASSEMBLER, вычисляющую значения функции F(x) в интервале [-10,12] при изменении переменной x шагом 2.<br><br> F(x) = a(x^2 + y^2 ) - b/(x^2 - y^2 ),<br>
Вопрос № 178508:

Доброго времени суток, уважаемые эксперты! Прошу помочь с такой задачей: необходима программа калькулятора, которая выполняет сложение, вычитание, умножение, деление, возведение в степень, извлечение корня. (можно в форме диалога). DOS, TASM.Заранее спасибо.

Отправлен: 19.05.2010, 21:14
Вопрос задал: Виктор Никанорович, Посетитель
Всего ответов: 1
Страница вопроса »


Отвечает Лысков Игорь Витальевич, Модератор :
Здравствуйте, Виктор Никанорович.
Наконец, дошли руки и до Вашего калькулятора (надеюсь, что еще актуально)...
Используются клавиши:
Esc - выход
c, BackSpace - вытирание
=, Enter - расчет
Tab - смена знака
s - sqrt (квадратный корень)
^ - x*x (квадрат)
Остальные понятно и так.
Обратите внимание, что, если число не помещается на индикатор, то младшие цифры (возможно значащие) усекаются!!!
Например, при возведении в квадрат или умножении... Обычно пишут "Error", я решил вот усекать...
Код:

.model tiny, C

LenX equ 19 ;ширина окна калькулятора
LenY equ 15 ;высота окна калькулятора
StartX equ ((80-LenX)/2) ;столбец левого верхнего угла
StartY equ ((25-LenY)/2) ;строка левого верхнего угла

;макро расчета смещения в видеобуфере по колонке и строке
CALCPOS MACRO x,y
mov al, y
mov ah, 80
mul ah
add ax, x
shl ax, 1
ENDM

;макро вывода кнопки в позиции (x,y), со строкой title, цветом colkey
;в bx смещение начала окна калькулятора
PRKEY MACRO x,y,title
local TLoop
CALCPOS x,y
add ax, bx
mov di, ax
lea si, title
mov ah, colkey
mov cx, 3
TLoop:
lodsb
stosw
loop TLoop
ENDM

.code
.286
.startup
mov ax, 0003h ;необходимо под XP для прямого вывода
int 10h ; в видеобуфер

call SaveScreen ;сохраним старое содержиое области экрана
mov ax, 0b800h
mov es, ax ;es - сегмент видеоданных
call PrintFon ;рисуем фон калькулятора с рамкой
call PrintKeys ;рисуем кнопки с индикатором
ReWrite: ;сюда идем, когда надо перерисовать
call PrintNum ;вывод числа на индикатор
WaitKey: ;цикл ожидания нажатия на кнопку
mov ah, 0
int 16h ;ж дем-с
;проверим код клавиши по двум таблицам:
;Keys1 - ASCII-коды, Keys2 - скан-коды
push es ;сохраним адресацию видеобуфера
push ds
pop es ;es=ds
lea di, Keys1 ;строка отрабатываемых кодов ASCII
mov cx, LnKeys1 ;длина строки кодов ASCII
repne scasb ;ищем
jne CmpKeys2 ;не нашли - на поиск по второй таблице
pop es ;восстановим сегмент видео
sub di, (offset Keys1)+1 ;di - смещение в таблице кодов
shl di, 1 ;будем адресовать слова
call PgKeys1[di] ;отработаем!
jnc ReWrite ;FC=0 - перерисовать
jmp WaitKey ;иначе на ожидание клавиши

CmpKeys2: ;ищем по скан-кодам
mov al, ah ;скан-код
lea di, Keys2 ;строка отрабатываемых скан-кодов
mov cx, LnKeys2 ;далее - аналогично предыдущему
repne scasb
pop es
jne WaitKey

sub di, (offset Keys2)+1
shl di, 1
call PgKeys2[di]
jnc ReWrite
jmp WaitKey

PrintNum proc ;вывод числовой строки String на индикатор
;считаем п озицию индикатора на экране
CALCPOS (StartX+2), (StartY+2)
mov di, ax ;смещение в буфере экрана
lea si, String ;строка
;найдем количество лидирующих нулей
mov cx, LenX-5 ;всего
sub cx, LenStr ;- длину выводимой строки
mov al, ' '
jcxz PNSign ;если нисколько не надо
PNSpaceLoop:
stosb ;выведем лидирующи пробелы
inc di
loop PNSpaceLoop
PNSign: ;выведем знак '-' или пробел
mov al, 0dh ;код '-' = 2dh
mul bSign ;al = 0dh (для 1) или 0
add al, ' ' ;получим или 2dh = '-', или 20h = ' '
stosb ;пишем
inc di
mov cx, LenStr ;число символов
PNNumLoop:
movsb ;копируем
inc di ;пропускаем атрибуты
loop PNNumLoop
ret
PrintNum endp

Exit proc ;выход
call RestoreScreen ;востановим старое содержимое экрана
mov ax, 4c00h
int 21h
Exit endp

BackSpace proc ;клавиша 'c' или backspace
cmp fNew, 0 ;есл и в режиме ввода числа
je BSContinue ; то на вытирание последнего символа
mov LenStr, 1 ; иначе, пишем 0
mov word ptr String, '0'
mov bSign, 0 ;сбросим знак
mov fNew, 0 ;установим режим ввода числа
mov PCount, 0 ;сбросим счетчик знаков после запятой
clc ;на прорисовку
ret
BSContinue: ;вводим число
mov bx, LenStr ;длина
dec bx ;уменьшим на 1
mov String[bx], 0 ;затрем последний символ
jnz BSSaveLen ;если больше чем 1 символ, то на сохр длины
mov bSign, 0 ;сбросим знак
mov String[bx], '0' ;зададим число 0
inc bx ;1 знак
BSSaveLen:
mov LenStr, bx ;сохраним длину
cmp PCount, 0 ;если только целое, то на выход
je BSRet
dec PCount ;иначе уменьшим число знаков после точки
BSRet:
clc ;перерисовать
ret
BackSpace endp

Sqrt proc ;квадратный корень, вызывается кнопкой 's'
call str2float ;преобразуем в вещественное число и в сопроцессор
fsqrt ;корень
call float2str ;преобразуем в строку String
mov fNew, 1 ;признак нового числа
clc ;перерисовать
ret
Sqrt endp

Square proc ;квадрат, вызывается кнопкой '^'
call str2float
fmul st, st(0) ;умножить на себя
call float2str
mov fNew, 1
clc
ret
Square endp

Oper proc ; / * - +
mov Operation, di ;сохраним адрес операции
mov fNew, 1 ;признак нового числа
call str2float ;преобразуем первый операнд в вещественное число
ret ; и в сопроцессор
Oper endp

Equal proc ;закончить операцию, вызывается '=' или Enter-ом
mov di, Operation ;тип операции
cmp di, -1 ;Если не была задана операция,
je Equal_None ; то не делаем ничего
fld st ;st(1)=st
call str2float ;преобразуем второй операнд в вещественное число
; и в сопроцессор
call Function[di] ;выполнить
call float2str ;преобразуем в строку String
mov fNew, 1 ;признак нового числа
mov Operation, -1 ;сбросим операцию
clc ;перерисовать
ret
Equal_None:
stc ;на ожидание клавиши
ret
Equal endp

Divide proc ;деление
fdivp
ret
Divide endp

Multiply proc ;умножение
fmulp
ret
Multiply endp

Substruct proc ;вычитание
fsubp
ret
Substruct endp

Summa proc ;сумма
faddp
ret
Summa endp

Sign proc ;смена знака
cmp LenStr, 1 ;проверим на 0
jnz SignOk
cmp String, '0'
je NoSign ;для 0 не меняем
SignOk:
xor bSign, 1 ;меняем признак знака '-'
clc ;перерисовать
ret
NoSign:
stc
ret
Sign endp

Point proc ;точка
cmp PCount,0 ;уже была введена?
jne PointRet
inc PCount ;инкремент позиции за точкой для следующей цифры
jmp Digit ;дальше, как цифры
PointRet:
stc ;больше одной точки запрещено
ret
Point endp

;Цифры 0-9
Dig0:
mov al,'0'
jmp Digit
Dig1:
mov al,'1'
jmp Digit
Dig2:
mov al,'2'
jmp Digit
Dig3:
mov al,'3'
jmp DigitDig4:
mov al,'4'
jmp Digit
Dig5:
mov al,'5'
jmp Digit
Dig6:
mov al,'6'
jmp Digit
Dig7:
mov al,'7'
jmp Digit
Dig8:
mov al,'8'
jmp Digit
Dig9:
mov al,'9'
Digit:
cmp fNew, 1 ;Если вводим новое число
jne DigitContinue
mov LenStr, 1 ;то сбрасываем его в 0
mov String, '0'
mov bSign, 0
mov fNew, 0
mov PCount, 0
DigitContinue: ;иначе, вводим очередной разряд
mov bx, LenStr ;проверим, есть ли место
cmp bx, LenX-5
je NoInsert ;некуда писать! (14 позиций)
cmp bx, 1 ;если один 0, то пишем вместо него
jnz NotFirst
cmp String, '0'
jne NotFirst
dec bx
jmp SetFirst
NotFirst:
inc LenStr ;инкремент количества
SetFirst:
mov String[bx], al ;пишем в конец строки символ
mov String[bx+1], 0 ;закрываем строк нулем
clc ;перерисовать
ret
NoInsert:
stc ;на ожидание кла виши
ret

;Преобразование строки в вещественное число в st сопроцессора
str2float proc ;преобразование строки в вещественное число
local ww:word ;для загрузки в сопроцессор
local dcount:word ;

fldz ;подготовим st=0
lea si, String ;числовая строка
mov dcount, 0 ;число знаков после точки = 0
s2fNext:
lodsb ;очередной символ
cmp al, 0 ;дошли до конца?
je s2fSign ;знак
cmp al, '.' ;точка
je s2fInc
and ax, 0fh ;иначе готовим разряд
mov ww, ax ; для загрузки в сопроцессор
cmp dcount, 0 ;если целая часть, то
je s2fMul10 ; на умножение на 10
mov cx, dcount ;иначе делим dcount раз на 10
fild ww ; очередной разряд
s2fdiv:
fidiv c10 ;делим dcount раз
loop s2fdiv
faddp ;складываем разряд за точкой с формируемым числом
s2fInc:
inc dcount ;для точки только увеличиваем dcount
jmp s2fNext ;пока не дойдем до конца

s2fMul10: ;целое число
fimul c10 ;умножаем старое на 10
fiadd ww ;и прибавляем очередной разряд
jmp s2fNext
s2fSign:
cmp bSign, 0 ;если bSign == 1
je s2fRet
fchs ;то меняем знак
s2fRet:
ret
str2float endp

;преобразование вещественного числа из st в строку по адресу String
float2str proc
uses es ;сохраним es
local dig:word ;буфер для извлечения целого из сопроцессора
local sTemp:byte:64 ;временный буфер для строки
push ds
pop es ;es=ds

lea di, sTemp ;здесь будем формировать строку
ftst ;Проверяем число
fstsw ax ;флаги в ax
sahf ;флаги в регистре флагов
jnz f2s_notZero ;не 0
mov LenStr, 1 ;длина 1
mov bSign, 0 ;сбрасываем знак
mov ax, '0' ;если 0, то выводим 0
stosw
jmp f2s_Ret ;на выход

f2s_notZero: ;не 0
mov bSign, 0 ; пока считаем, что положительное
jnc f2s_1 ;если оно отрицательное,
mov bSign, 1 ; то помечаем минус
fchs ; и оставляем модуль числа.
; Пояснение далее пойдёт на примере. ; ST(0) ST(1) ST(2) ST(3) ...
; Отделим целую часть от дробной. ; 73.25 ... что-то не наше
f2 s_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
; Если она всё-таки ненулевая, выведем точку
lea ax, sTemp
mov cx, di
sub cx, ax
sub cx, 63
neg cx
mov al, '.'
stosb
; Помножим дробную часть на десять
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
; и скопировать в буфер String
lea si, sTemp
lea di, String
mov LenStr, 0 ;длина
f2s_6:
lodsb
stosb ;копируем 1 байт
inc LenStr ;считаем
cmp LenStr, 14 ;копируем только 14 байт !!! (если получится число
; с большим чем 14 байт знаков, то последние усекутся)
je f2s_7 ;насильно закрываем нулем!
cmp al, 0
jne f2s_6 ;копирование завершаем по 0
dec LenStr ;отнимем 1 (посчитался нулевой байт)
f2s_7:
mov byte ptr [di], 0 ;закроем нулем (для случая обрезания)
f2s_Ret:
ret
float2str endp

;Вывод кнопок калькул ятора
PrintKeys proc
CALCPOS StartX, StartY ;позиция на экране
mov bx, ax ;база (для макро)
;x,y,name ;надп. :клавиши : действие
PRKEY 2, 4, key_c ;" c " : c, backspace : вытирание
PRKEY 6, 4, key_sn ;"+/-" : Tab : знак
PRKEY 10, 4, key_sq ;"sqr" : s : sqrt
PRKEY 14, 4, key_st ;"x^2" : ^ : x*x
PRKEY 2, 6, key_7 ;" 7 " : 7 : 7
PRKEY 6, 6, key_8 ;" 8 " : 8 : 8
PRKEY 10, 6, key_9 ;" 9 " : 9 : 9
PRKEY 14, 6, key_dv ;" / " : / : /
PRKEY 2, 8, key_4 ;" 4 " : 4 : 4
PRKEY 6, 8, key_5 ;" 5 " : 5 : 5
PRKEY 10, 8, key_6 ;" 6 " : 6 : 6
PRKEY 14, 8, key_ml ;" * " : * : *
PRKEY 2,10, key_1 ;" 1 " : 1 : 1
PRKEY 6,10, key_2 ;" 2 " : 2 : 2
PRKEY 10,10, key_3 ;" 3 " : 3 : 3
PRKEY 14,10, key_ms ;" - " : - : -
PRKEY 2,12, key_0 ;" 0 " : 0 : 0
PRKEY 6,12, key_pt ;" . " : . : .
PRKEY 10,12, key_eq ;" = " : =, Enter : посчитать
PRKEY 14,12, key_pl ;" + " : + : +

;индикатор
CALCPOS 2,2
add ax, bx
mov di, ax
mov ah, colscr
mov al, ' '
mov cx, LenX-4
rep stosw

ret
PrintKeys endp

;вывод фона с рамкой
PrintFon proc
CALCPOS StartX, StartY ;стартовая позиция
mov di, ax
mov ah, colfon ;цвет фона
mov al, lu ;левый верхний угол
stosw
mov al, hor ;горизонтальная линия
mov cx, LenX-2
rep stosw
mov al, ru ;правый верхний угол
stosw
mov cx, LenY-2 ;число внутренних строк
PFLoop:
push cx
add di, (80-LenX)*2 ;на следующую строку
mov al, ver ;вертикальная черта
stosw
mov al, ' ' ;пробелы
mov cx, LenX-2
rep stosw
mov al, ver ;вертикальная черта
stosw
pop cx
loop PF Loop
add di, (80-LenX)*2 ;на последнюю строку
mov al, ld ;левый нижний угол
stosw
mov al, hor ;горизонтальная линия
mov cx, LenX-2
rep stosw
mov al, rd ;правый нижний угол
stosw
ret
PrintFon endp

SaveScreen proc ;сохраняем область экрана, куда будем выводить
uses ds,si,di,cx,bx
mov ah, 3
mov bh, 0
int 10h
mov CursorForm, cx ;сохраним форму курсора

mov cx, 2000h
mov ah, 1
int 10h ;скроем курсор

mov ax, 0b800h
mov ds, ax ;копируем с экрана
CALCPOS StartX, StartY
mov si, ax
lea di, OldScreen ;буфер для сохранения
mov cx, LenY
SaveRowLoop:
push cx
mov cx, LenX
rep movsw
pop cx
add si, (80-LenX)*2
loop SaveRowLoop
ret
SaveScreen endp

RestoreScreen proc ;восстанавливаем область экрана
uses si,di,cx ;аналогично, только в другую сторону
CALCPOS StartX, StartY
mov di, ax
lea si, OldScreen
mov cx, Le nY
RestoreRowLoop:
push cx
mov cx, LenX
rep movsw
pop cx
add di, (80-LenX)*2
loop RestoreRowLoop

mov cx , CursorForm ;восстанавливаем форму курсора
mov ah, 1
int 10h
ret
RestoreScreen endp

.data
;символы псевдографики для рисования рамки
lu db 0dah
ru db 0bfh
ld db 0c0h
rd db 0d9h
hor db 0c4h
ver db 0b3h

;цвета
colfon db 3bh ;цвет фона
colkey db 17h ;цвет клавиш
colscr db 71h ;цвет индикатора

;строки, выводимые на клавишах
key_0 db ' 0 '
key_1 db ' 1 '
key_2 db ' 2 '
key_3 db ' 3 '
key_4 db ' 4 '
key_5 db ' 5 '
key_6 db ' 6 '
key_7 db ' 7 '
key_8 db ' 8 '
key_9 db ' 9 '
key_pt db ' . '
key_eq db ' = '
key_pl db ' + '
key_ms db ' - '
key_ml db ' x '
key_dv db ' / '
key_st db 'x^2'
key_sq db 'sqr'
key_c db ' c '
key_sn db '+/-'

;строка для поиска отрабатываемых клавиш (по ASCII)
Ke ys1 db '/*-+^=.0123456789',8,1bh,9,0dh
LnKeys1 equ $-Keys1 ;длина
;адреса подпрограмм отработки действий по клавишам
PgKeys1 dw Oper,Oper,Oper,Oper,Square,Equal,Point
dw Dig0,Dig1,Dig2,Dig3,Dig4,Dig5,Dig6,Dig7,Dig8,Dig9
dw BackSpace,Exit,Sign,Equal

;строка для поиска отрабатываемых клавиш (по скан-кодам)
Keys2 db 2eh, 1fh
LnKeys2 equ $-Keys2
PgKeys2 dw BackSpace, Sqrt

;таблица отработки функций /,*,-,+
Function dw Divide,Multiply,Substruct,Summa

;буфер, содержащий числовую строку для вывода на экран
String db '0',14 dup (0)

;признак отрицательного числа 0/1 : -/+
bSign db 0

;длина строки String
LenStr dw 1

c10 dw 10 ;константа 10
PCount dw 0 ;для контроля ввода точки
fNew dw 0 ;признак нового числа
Operation dw -1 ;тип операции для /,*,-,+,
; если не была указана операция, то -1

.data?
CursorForm dw ? ;сохраняем форму курсора
OldScreen dw LenY*LenX dup (?) ;буфер для сохранения фрагмента экрана, где рисуем калькулятор

end

-----
Удачи!

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

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

  • Вопрос № 178856:

    Здравствуйте, уважаемые эксперты. Помогите разобраться с реализацией алгоритма Брезенхейма в приведённой ниже процедуре. В Википедии алгоритм описан как увеличение X, при увеличении значения ошибки на величину наклона S, где S = Y1 - Y0/X1 - X0, т.е. как соотношение катетов. Если ошибка превысила 0.5, линия стала ближе к следующему Y, поэтому мы увеличиваем Y на единицу,
    одновременно уменьшая значение ошибки на 1.
    1 В приведённой ниже процедуре из книги Кулакова мне непонятно, с какой целью делается
    умножение на 2 командой shl AX,1.
    2 Для чего потом вычитается sub AX,[DeltaX]. Как-то странно получается: [DeltaY] увеличили в 2 раза, а [DeltaX] оставили без изменений. Величина наклона S изменилась же, а должна быть постоянной. В комментариях пишется, что командой sub AX,[DeltaX] определяется ошибка накопления, а в чём тут ошибка накопления, я не понимаю.
    3 Потом ещё раз вычитается sub AX,[DeltaX] и заносится в [DeltaYx2MinusDeltaXx2].
    Для чего эта уже вторая ошибка накопления? Разница между [ErrorTerm] и [DeltaYx2MinusDeltaXx2] очень большая.
    4 В процедуре для вывода точки по X или Y значение ошибки сравнивается с 0 (cmp [ErrorTerm],0), а в Википедии говорится о сравнении с 0,5. Немножко посчитал, у меня дробных величин не получилось, все числа целые.
    Процедуру я немножко изменил: 32-битные регистры перевёл в 16.

    Отправлен: 04.06.2010, 16:16
    Вопрос задал: Adsorores, Посетитель
    Всего ответов: 1
    Страница вопроса »


    Отвечает Лысков Игорь Витальевич, Модератор :
    Здравствуйте, Adsorores.
    Если ответить коротко, то данные формулы - результат довольно длинных преобразований.
    Которые можете посмотреть, например, вот здесь, рассказано все очень подробно, со всеми выкладками. Приведена программа на С.

    Попутно замечу. Подправьте pushad/popad на pusha/popa. И в одном месте остался edx

    -----
    Удачи!

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

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

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

  • Вопрос № 178859:

    Здравствуйте уважаемые эксперты! У меня такой вопрос, точне нужна помощь. Задача такая вообщем, нужно реализовать на ассемблере программу, которая с клавиатуры 16-ричное двухзначное (восьмиразрядное) число, переводит его в 10-чное и 2-чное, а результат выводить на экран. Помогите пожалуйста. Я тут собрал из частей код но не смог оптимизировать

    Отправлен: 04.06.2010, 19:06
    Вопрос задал: Артем Борисовский, Посетитель
    Всего ответов: 2
    Страница вопроса »


    Отвечает amnick, Студент :
    Здравствуйте, Артем Борисовский.

    В приложении - исправленная программа. Замечания помечены ;!
    Ваша программа рассчитана не только на 2-значные, но и на 16-ричные числа до 4-х значащих цифр. Буквы должны быть в верхнем регистре.
    Преобразование в 10-тичную и 2-ичную системы правильное, но слишком маленькие буфера для результатов. Кроме того, перед преобразованием в 2-ичную систему число уже было утеряно.
    Чуток поправил сообщения.

    Работу программы проверил.

    Успехов!

    Приложение:

    Ответ отправил: amnick, Студент
    Ответ отправлен: 04.06.2010, 22:29
    Номер ответа: 261886

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

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

  • Отвечает Лысков Игорь Витальевич, Модератор :
    Здравствуйте, Артем Борисовский.
    Моя версия подправленной программы.
    Вводит 1 байт, не более 2 hex-цифр из командной строки.
    Добавил проверку на ошибки: проверяются символы на корректность, число цифр
    Поменял вывод десятичного числа.
    Код:
    cod segment 
    assume cs:cod,ds:cod
    org 100h
    begin:
    mov dx,offset Start
    call Message
    ;Чтение из командной строки
    mov bx,80h
    ; получение длины
    xor cx,cx
    mov cl,[bx]
    jcxz ErrorNoCmd ;проверим на ноль - ничего не задано
    ; вставлем число в регистр dx
    dec cx
    cmp cx,2 ;ждем 1 или 2 hex цифры!
    ja ErrorBigCmd ;если больше, то ошибка
    lea si,[bx+2]
    xor dx,dx
    PutNumbToDX:
    ; вставляем число в регистр dx
    shl dx,4
    lodsb
    or al,20h ;чтобы б уковки 'a' и 'A' стали одинаковыми - 'a'
    ;на цифры не влияет!
    sub al,'0'
    jc ErrorNum ;<'0' - ошибка
    cmp al,9
    jbe TransDone ;'0'-'9' - ok
    sub al,('a'-'0')-10
    jc ErrorNum ;'9'-'a' - ошибка
    cmp al,0fh
    ja ErrorNum ;>'f' - ошибка
    TransDone:
    or dl,al
    loop PutNumbToDX

    ;Конвертируем в десятичную и выводим на экран
    push dx
    mov dx,offset ResPrompt
    call Message
    pop ax ;в ax число
    mov bx,10 ;будем делить на 10
    mov di,offset Symbols ;буфер для числовой строки
    xor cx,cx ;будем считать
    push ax ;сохраним для дальнейшего преобразования в двоичный код
    GetDigit: ;процедура перевода в десятичную СС
    xor dx,dx
    div bx ;остаток - очередная младшая цифра
    push dx ;сохраним в стеке
    inc cx ;считаем
    test ax,ax ;пока что-то есть
    jnz GetDigit
    PutDigit: ;выводим в обратном поряд ке
    pop ax
    add al,'0'
    stosb
    loop PutDigit ;по всем цифрам
    call PrintNum ;дооформим строку и выведем
    ; Конвертируем в двоичную и выводим на экран
    mov dx,offset ResPromptBin
    call Message
    pop dx ;наше число
    mov cx,8 ;8 бит
    mov di,offset Symbols ;в том же буфере
    GetBin: ; процедура перевода в двоичную СС
    xor ax,ax
    shl dl,1 ;у нас байт, с ним и работаем
    adc al,'0'
    stosb
    loop GetBin
    mov al,'b' ;добавим в конце 'b'
    stosb
    call PrintNum ;дооформим строку и выведем
    Exit: ; Выход
    mov dx,offset Finish
    jmp Message

    ;ошибки
    ErrorNoCmd: ;без параметра
    mov dx,offset NoCmd
    jmp Message
    ErrorNum:
    mov dx,offset ErrNum;не hex-число
    jmp Message
    ErrorBigCmd:
    mov dx,offset BigCmd;больше 2-х цифр
    jmp Message
    PrintNum: ;вывод числовой строки
    mov ax,0d0ah ;добавим перевод строки
    stosw
    mov al,'$' ;добавим '$& #39; для функции 9
    stosb
    mov dx,offset Symbols
    Message: ;процедура вывода на экран
    mov ah,09h
    int 21h
    retn

    Start db 'Start !',0ah,0dh,'$'
    NoCmd db 'No specified symbols in CMD !',0ah,0dh,'$'
    BigCmd db 'Many symbols in CMD! Must be two symbols',0ah,0dh,'$'
    ErrNum db 'Not hex number!',0ah,0dh,'$'
    ResPrompt db 'Result in digit: ','$'
    ResPromptBin db 'Result in bin: ','$'
    Symbols db 16 dup (?)
    Finish db 'Finish!',0ah,0dh,'$'

    cod ends
    end begin

    -----
    Удачи!

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

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

  • Вопрос № 178862:

    Уважаемые эксперты! Помогите пожалуйста разработать программу на языке ASSEMBLER, вычисляющую значения функции F(x) в интервале [-10,12] при изменении переменной x шагом 2.<br><br>

    F(x) = a(x^2 + y^2 ) - b/(x^2 - y^2 ),<br>
    где a = -2.5; b = 0.563; y=4

    Отправлен: 05.06.2010, 02:31
    Вопрос задал: Лисневская Мария Геннадьевна, Посетитель
    Всего ответов: 1
    Страница вопроса »


    Отвечает Лысков Игорь Витальевич, Модератор :
    Здравствуйте, Лисневская Мария Геннадьевна.
    Примерно так:
    Код:
    ;Программа вычисляет значения функции F(x) в интервале [-10,12] 
    ;при изменении переменной x шагом 2
    ;F(x) = a(x^2 + y^2 ) - b/(x^2 - y^2 ),
    ;где a = -2.5; b = 0.563; y=4
    .model tiny, C
    .286
    .code
    .startup

    lea di, fx
    mov bx, -10
    calc_loop:
    cmp bx, 12
    jg finish
    call f, bx
    fstp dword ptr [di]
    add di, 4
    add bx, 2
    jmp calc_loop

    finish:
    mov ax, 4c00h
    int 21h

    ;функция принимает целый параметр Х в стеке
    ;возвращает в st результат
    ;в случае деления на 0 возвращает 0 и FC=1
    ;иначе FC=0
    f proc x:word
    fild x ;x
    fmul st, st(0) ;x^2
    fld y ;y,x^2
    fmul st, st(0) ;y^2,x^2
    fld st ;y^2, y^2,x^2
    fadd st(0),st(2) ;y^2+x^2,y^2,x^2
    fmul a ;a(y^2+x^2),y^2,x^2
    fxch st(2) ;x^2,y^2,a(y^2+x^2)
    fsubrp ;x^2-y^2,a(y^2+x^2)

    fldz ;загрузим 0
    fcomp st(1) ;сравним с 0 (с удалением 0)
    fstsw ax ;флаги в ax
    sahf ;флаги в регистров флагов
    jz ZeroDevide ;=0 -> делить не будем!
    fdivr b ;b/(x^2-y^2),a(y^2+x^2)
    fsubr ;a(y^2+x^2)-b/(x^2-y^2)
    clc
    ret
    ZeroDevide:
    fstp st(1) ;уберем из стека st(1) и вернем 0
    stc
    ret
    f endp

    .data
    a dd -2.5
    b dd 0.563
    y dd 4.

    .data?
    fx dd 12 dup (?)

    end


    В случае деления на 0 возвращает 0 и FC=1. При желании можно проанализировать.
    -----
    Удачи!

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

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

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

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

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

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

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

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

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

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


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

    В избранное