Хостинг портала RFpro.ru: Московский хостер Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64 РАССЫЛКИ ПОРТАЛА RFPRO.RU Чемпионы рейтинга экспертов в этой рассылке Номер выпуска: | 1325 | Дата выхода: | 25.04.2010, 01:00 | Администратор рассылки: | Лысков Игорь Витальевич, Модератор | Подписчиков / экспертов: | 319 / 62 | Вопросов / ответов: | 1 / 1 | IRC-канал по теме: | #assembler | Вопрос № 177889: Доброго времени суток дорогие Эксперты! помогите решить парочку задач на ассемблере: 1) Написать программу для выполнения сложения 2х целых чисел размера N байт (N>0) пре... Вопрос № 177889: Доброго времени суток дорогие Эксперты!
помогите решить парочку задач на ассемблере: 1) Написать программу для выполнения сложения 2х целых чисел размера N байт (N>0) представленных в дополнительном коде коде.
2)Написать программу для выполнения деления 2х N-значных знаковых десятичных чисел (N>1) представленных в неупакованном формате представления.
Хар-ки: 1)процессор intel core 2 solo CPU U3500 2)window vista home premium 32х разрядная 3)Turbo Assembler Version 4.1 в папке asm находится фаил TASM поэтому думаю он предпочтителен 4)вычисления производить в сопроцессоре
Заранее спасибо дорогие эксперты! Отправлен: 17.04.2010, 14:46 Вопрос задал: Юдин Евгений Сергеевич, 1-й класс Всего ответов: 1 Страница вопроса » Отвечает Лысков Игорь Витальевич, Модератор : Здравствуйте, Юдин Евгений Сергеевич. Программа по первому вопросу. Можно было использовать 32-битные регистры. Но мне захотелось продемонстрировать, как можно обойтись 16-битными... При желании, можете легко переделать на 16-битные данные... Все необходимое есть. 
Код: ;Складываем x + y и выводим результат ;Разрядность данных - двойное слово (4 байта) ;Используем исключительно 16-битные регистры
dsegX segment para public 'data' x dd -2147400012 dsegX ends
dsegY segment para public 'data' y dd 1234 dsegY ends
dseg segment para public 'data' sX db 'x = $' sY db 0dh,0ah,'y = $' sSum db 0dh,0ah,'Sum = $' sPress db 0dh,0ah,'Press any key$' dseg ends
LOCALS @@ ;чтобы метки, начинающиеся на @@ были локальными cseg segment para public 'code' assume cs:cseg, ds:dseg, es:nothing start: ;точка входа mov ax, dseg mov ds, ax ;ds - сегмент данных
lea dx, sX ;x = mov ah, 9 int 21h
mov ax, dsegX ;переменную x адресуем через сегментный регистр es mov es, ax mov ax, word ptr es:x ;младшее слово mov dx, word ptr es:x+2 ;старшее слово call WriteDWordDEC_signed ;выведем знаковое двойное слово
mov si, ax ;сохраним x mov di, dx
lea dx, sY ;y = mov ah, 9 int 21h
mov ax, dsegY ;аналогично берем значение y mov es, ax mov ax, word ptr es:y mov dx, word ptr es:y+2 call WriteDWordDEC_signed ;выведем
add si, ax ;найдем сумму adc di, dx
lea dx, sSum ;Sum = mov ah, 9 int 21h
mov ax, si ;значение сум мы mov dx, di call WriteDWordDEC_signed ;выведем
lea dx, sPress ;Press any key mov ah, 9 int 21h
mov ah, 0 ;чтобы окно сразу не закрывалось int 16h
mov ax, 4c00h ;выход в ДОС int 21h ;Вывод знакового двойного слова из DX:AX ;если отрицательное, выводит минус, превращает в ;положительное и далее выводит как беззнаковое WriteDWordDEC_signed proc push ax dx ;сохраним число
or dx, dx ;проверим знак jns @@_no_sign push ax mov al, '-' ;выведем '-' int 29h pop ax not ax ;изменение знака на + not dx add ax, 1 adc dx, 0 @@_no_sign: CALL writeDWordDEC ;выводим положительное беззнаковое число
pop dx ax ret WriteDWordDEC_signed endp
;Вывод беззнакового двойного слова из DX:AX ;просто делением на 10 не получится, возможно переполнение ;переполнение возможно и при делении на 10000 ;поэтому делим на 100000, причем в два этапа: ;сначала на 50000 (что помещается в слово), затем на 2 ;затем выводим частное от деления и остаток (5-значное цисло!) ;разные ньюансы смотрим по ходу... writeDWordDEC proc push si cx dx bx ax xor cx, cx ;старшее слово остатка от деления на 100000, ; т.к. макс значение 99999 не помещается в слово! mov bx, 50000 ;делим сначала на 50000 div bx shr ax, 1 ;и на 2 jnc @@1 ;если нет переноса, то остаток < 50000 ! add dx, 50000 ;добавим к остатку 50000 ! adc cx, 0 ;и учтем перенос ! @@1: xor si, si ;количество выводимых цифр в остатке. ;0 - выводим остаток, сколько есть значащих цифр ;5 - если есть частное от деления на 100000, ; то у остатка должно быть обязательно 5 значащих цифр! test ax, ax ;проверим частное от деления на 100000 jz @@2 ;выводим остаток как есть call writeWordDEC ;выводим частное, как слово mov si, 5 ;и 5 обязательных циф р остатка! @@2: mov ax, dx ;остаток в dx:ax mov dx, cx call write5DigDEC ;выводим
pop ax bx dx cx si ret writeDWordDEC endp
;вывод на экран 5 дес цифр в DX:AX, воспринимается как беззнаковое ;SI - количество обязательных цифр write5DigDEC proc mov bx, 10 ;будем делить на 10 xor cx, cx ;счетчик цифр @@1: div bx ;делим dx:ax на bx push dx ;сохраним в стеке очередную цифру xor dx, dx ;для следующего деления inc cx ;считаем цифры or ax, ax ;есть еще разряды? jnz @@1 ;пока не разложим на цифры mov al, '0' ;выведем незначащие нули! mov dx, cx ;число полученных цифр @@2: cmp dx, si ;сравним с максимальным jae @@3 ;для 0 сразу уходим, для 5 - пока не добавим int 29h ; inc dx ; необходимое количество незначащих нулей jmp @@2 @@3: ;цикл вывода полученного числа pop ax ;извлекаем из стека очередной разряд add al, '0' ;превращаем в символ int 29h ;выводим LOOP @@3 ;по всем цифрам
ret write5DigDEC endp
; вывод на экран сло ва в AX, воспринимается как беззнаковое writeWordDEC proc push cx dx bx ax
mov bx, 10 ;делим на 10 xor cx, cx ;счетчик цифр @@1: xor dx, dx ;подготавливаемся к делению div bx ;делим dx:ax на bx push dx ;сохраним остаток - очередную цифру inc cx ;считаем цифры or ax, ax ;есть еще разряды? jnz @@1 ;пока не разложим на цифры @@2: ;цикл вывода полученного числа pop ax ;извлекаем из стека очередной разряд add al, '0' ;превращаем в символ int 29h ;выводим LOOP @@2 ;по всем цифрам
pop ax bx dx cx ret writeWordDEC endp
;вывод на экран слова в AX как знакового ;если отрицательное, выводит минус, превращает в ;положительное и вызывает подпрограмму writeWordDEC WriteWordDEC_signed proc push ax or ax, ax ;проверим на знак jns @@_no_sign ;если положительное, то просто выводим push ax mov al, '-' ;выводим '-' int 29h pop ax neg ax ;изменение знака на + @@_no_sign: CALL writeWordDEC ;выводим беззнаковое pop ax ret WriteWordDEC_signed endp
cseg ends
end start
Вторая программа делит знаковые 4-х разрядное BCD-число на 2-х разрядное BCD число Остаток отбрасываем. Ограничился более сложным случаем, а именно: делением в виде BCD Полагаю, требовалось именно это...
Код: ;Делим неупакованные числа x (разрядности 4) на y (разрядности 2) и выводим результат ;числа хранятся в формате "старший первым", знак - в виде бита 7, т.е. маска 80h в старшем байте dsegX segment para public 'data' x db 83h,6,9,8 dseg X ends
dsegY segment para public 'data' y db 81h,2 dsegY ends
dseg segment para public 'data' XdivY db 0,0,0,0 sX db 'x = $' sY db 0dh,0ah,'y = $' sQuot db 0dh,0ah,'Quotient = $' sPress db 0dh,0ah,'Press any key$' dseg ends
cseg segment para public 'code' assume cs:cseg, ds:dseg, es:nothing start: ;точка входа mov ax, dseg mov ds, ax ;ds - сегмент данных
lea dx, sX ;x = mov ah, 9 int 21h
mov ax, dsegX ;переменную x адресуем через сегментный регистр es mov es, ax lea bx, x ;смещение для вывода mov di, bx ;смещение для деления mov cx, 4 call PrBCD ;выводим cx=4 байт BCD по адресу es:bx
lea dx, sY ;y = mov ah, 9 int 21h
mov ax, dsegY ;переменную y адресуем через сегментный регистр es mov es, ax lea bx, y mov si, bx ;смещение для деления mov cx, 2 call PrBCD ;аналогично
lea dx, sQuot ;Quotient = mov ah, 9 int 21h
push ds mov ax, dsegX ;переменную x адресуем es:di< br> mov es, ax mov ax, dsegy ;переменную y адресуем ds:si mov ds, ax
lea bx, XdivY ;смещение результата в сегменте dseg. ; сегмент зададим внутри попрограммы ! call div_BCD_4_2 ;делим pop ds
mov ax, dseg mov es, ax mov cx, 4 call PrBCD ;выводим результат: cx=4 байт BCD по адресу es:bx
lea dx, sPress ;Press any key mov ah, 9 int 21h
mov ah, 0 ;чтобы окно сразу не закрывалось int 16h
mov ax, 4c00h int 21h
;Вывод cx байт BCD по адресу es:bx PrBCD proc test byte ptr es:[bx], 80h ;проверим знак jz PrSearchNonZero mov al, '-' ;выведем минус int 29h PrSearchNonZero: ;найдем первый не 0! mov al, es:[bx] inc bx and al, not 80h ;сбрасываем старший бит, одновременно проверяем на 0 loopz PrSearchNonZero ;циклим, пока cx!=0 и al!=0 jcxz PrLast ;все 0, выводим один 0 PrLoop: ;цикл вывода значащих цифр, кроме последней ( !) or al, '0' ;в символ int 29h mov al, es:[bx] ;читаем следующую цифру inc bx loop PrLoop PrLast: ;выведем последнюю цифру or al, '0' int 29h ret PrBCD endp
;делим BCD es:di на ds:si ;результат пишем в dseg:bx div_BCD_4_2 proc push ds di ax cx dx bx ;преобразуем делитель в двоичное число mov ax, [si]
mov dh, al and dh, 80h ;сохраним знак делителя
and al, not 80h ;сбросим знак xchg ah, al ;поменяем местами (надо для aad) aad mov dl, al ;делитель
mov ax, dseg mov ds, ax ;загрузим ds сегментом dseg (для частного)
mov al, es:[di] ;определим знак делимого and al, 80h xor dh, al ;знак частного !
mov ah, 0 ;старший разряд пока = 0 mov cx, 4 ;число проходов div_BCD_loop: mov al, 10 ;умножим старший разряд на 10 mul ah push cx ;сохраним счетчик проходов mov cl, es:[di] ;очередной младший р азряд inc di ;смещение следующего and cx, 007fh ;сбросим знак add ax, cx ;получим ст*10+мл pop cx ;восстановим счетчик div dl ;делим на делитель mov [bx], al ;очередная цифра частного, в ah остаток, ; который будет старшим разрядом на следующем шаге inc bx ;смещение следующейцифры частного loop div_BCD_loop pop bx ;восстановим смещение начала частного or [bx], dh ;и установим знак частного! pop dx cx ax di ds ;восстановим остальные регистры RET div_BCD_4_2 endp
cseg ends end start ----- Удачи! Ответ отправил: Лысков Игорь Витальевич, Модератор Ответ отправлен: 22.04.2010, 14:05 Номер ответа: 260957 Украина, Кировоград Тел.: +380957525051 ICQ # 234137952 Mail.ru-агент: igorlyskov@mail.ru Абонент Skype: igorlyskov Вам помог ответ? Пожалуйста, поблагодарите эксперта за это! Как сказать этому эксперту "спасибо"? | Отправить SMS #thank 260957 на номер 1151 (Россия) | Еще номера » | Оценить выпуск » Нам очень важно Ваше мнение об этом выпуске рассылки! Скажите "спасибо" эксперту, который помог Вам! Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА на короткий номер 1151 (Россия) Номер ответа и конкретный текст СМС указан внизу каждого ответа. Полный список номеров » * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов) ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются. *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании. |
Комментариев нет:
Отправить комментарий