Нужно преобразовать дв. число в дв.-десятичное (неважно, пакованное или нет -- главное получить тетрады составляющих число циферок). Контроллер серии MCS51 (8051). Он работает только с байтами (складывание, умножение, деление,..), поэтому ничего лучше не придумал, как "метод двух счетчиков", когда есть два счетчика: в цикле к ним прибавляется 1, причем к первому как к обычному числу, а ко второму, как к двоично-десятичному, с коррекцией. Цикл идет до тех пор, пока первый счетчик не сравняется с исходным числом, тогда во втором будет его упакованное BCD представление. Но есть проблема. Опять же из-за работы только с байтами. У меня два регистра R6:R7 образуют как бы 16-битное число, работаю с отдельными регистрами: Код (Text): mov DPTR,#0 ; DPTR=0 (он сост. из DPH:DPL -- ст. и младший байт) mov R6,#0 ; R6=0 mov R7,#0 ; R7=0 check: mov A,DPL ; A=DPL cjne A,31h,cycle ; тут сравнение DPTR с 2хбайтным числом по адресу 30h mov A,DPH cjne A,30h,cycle sjmp stop ; вот собсна цикл cycle: inc DPTR ; вот тут 8051 МОЖЕТ работать ; сразу 16-битным DPTR, на этом лафа кончилась mov A,R7 ; A=R7 add A,#1 ; A++ da A ; десятичная коррекция A mov R7,A ; R7=A mov A,R6 ; A=R6 addc A,#0 ; A+флаг переноса da a ; дес. уоррекция mov R6,A ; R6=A sjmp check ; возврат в цикл stop: Интересует вопрос, можно ли так работать с дв. десятичным числом? Т. е. прибавлять к младшему байту единицу, дес. коррекция, потом к старшему прибавить влаг переноса и опять коррекция. Равносильно ли это прибавлению 1 ко всему 2хбайтовому числу 1 и дес. коррекции?
Ой. Раньше редактирование было, сейчас кнопочку не найду... Поправки: ...двоично-десятичное число, т. е. это второй счётчик, где по окончании должен оказаться результат. Вторая "1" лишняя.
Вот нашел код. Может поможет. Код (Text): ;29 Oct 00 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ;BINDECW is called to convert the unsigned integer in r5,r4 to one to ; five decimal ASCII characters and place them in the caller's 5-byte ; direct memory buffer. BINDECW calls DIV16U to do the division. ; ;call: ; mov r5,MSBs ; mov r4,LSBs ; mov r0,#buffer ; call BINDECW ; ;return: ; ; r0 ==> byte above last ASCII code placed in caller's buffer ; all other registers saved ; ;examples: ; ;input: return (buffer+): ; r5,r4 +0 +1 +2 +3 +4 r0=> ; 0,0 "0" n.c. n.c. n.c. n.c. +1 ; 0,50 "5" "0" n.c. n.c. n.c. +2 ; 1,0 "2" "5" "6" n.c. n.c. +3 ; 255,255 "6" "5" "5" "3" "5" +5 ; ;n.c. = no change ; ;Possible future improvements: ; (1) Replace DIV16U with a routine that divides 16 by 8 for faster ; operation. ; ;Notes: Re-entrancy not supported. counter and save_r0 would be ; destroyed. ; ;Original author: John Veazey, Ridgecrest, CA, 29 Oct 00 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; dseg counter: ds 1 save_r0: ds 1 cseg BINDECW: ; ;Save address of caller's buffer ; mov save_r0,r0 ; ;Divide caller's input by 10, four times saving each remainder on the ; stack as the next BCD digit. The first remainder produced is the 1's BCD ; digit,the second the 10's, third 100's, fourth 1000's, fifth 10,000's. mov counter,#4 bdw22: mov r1,#0 mov r0,#10 call DIV16U ;r5,r4 = (r5,r4)/(r1,r0) mov a,r6 ; r7,r6 = remainder push acc djnz counter,bdw22 mov a,r4 ;Last quotient is the last remainder push acc ; ;Pop the stack until the MS non-zero digit is found ; mov counter,#5 mov r0,save_r0 bdw44: pop acc jnz bdw60 djnz counter,bdw44 mov @r0,#"0" ;Five zeros found inc r0 sjmp bdw90 ; ;Convert BCD to ASCII and save in caller's buffer ; bdw60: add a,#"0" mov @r0,a inc r0 ; ;Continue loop until all BCD digits removed from stack ; djnz counter,bdw74 sjmp bdw90 bdw74: pop acc sjmp bdw60 ; ;Return to caller ; bdw90: ret ;end BINDECW.ASM
S_Alex Это не то. Попробую объяснить проблему, не пребегая к микроконтроллеру, т. к. не все его знают. Рассмотрим два варианта: 1) Есть 16-битное число X, которое рассматривается как упакованное двоично-десятичное (bcd) число. К нему прибавим единицу и сделаем десятичную коррекцию (на MCS-51 это команда "da", на x86 тоже есть подобная команда). Получили какой-то результат P=X+1 (все в BCD формате), напр. 7899h+1h = 789Ah = (дес. коррекция, в данном случае это прибавление 6) = 7900h. 2) Есть два байта X и Y, которые отождествляют 16-битное число X:Y (Y -- мл. часть). Рассматриваются тоже как bcd числа. Я хочу прибавить к нему 1. Для этого я прибавляю к младшей части 1, и делаю дес. коррекцию. Затем прибавляю к старшей части флаг переноса ("addc A,#0" на MCS-51, на x86 это вроде бы "adc ax,0", только "A" -- 8битный регистр) и делаю его дес. коррекцию. Вопрос: получим ли мы такой же результат, как в первом случае?
Ra!N Равносильно в том смысле, что будет получен корректный результат. Более того, во всех интеловских процессорах обработка двоично-десятичных чисел возможна только по байтам независимо от разрядности процессора (если не прибегать к помощи арифметического сопроцессора, но это отдельная песня). Дело в том, что для десятичной коррекции необходимо фиксировать факт переноса между тетрадами, и для обработки чисел, превышающих байт, необходимо фиксировать такой перенос для каждой из тетрад (кроме самой старшей, из которой происходит "нормальный" перенос), ну а Интел предусмотрела лишь один флаг вспомогательного переноса что в 8-разрядных, что в 16-32-разрядных процах -- из 3-го разряда в 4-й (а в 64-разрядных АМД, а вслед за ней и Интел и вовсе убрали поддержку двоично-десятичных операций -- команды коррекции работают только в 16- и 32-разрядных режимах, но не в 64-разрядном). Вот в мэйнфреймах вообще никаких коррекций не надо: там просто есть нормальные команды для выполнения операций над двоично-десятичными числами переменной длины, расположенными в памяти...
Ra!N http://abc.vvsu.ru/Books/ebooks_iskt/%DD%EB%E5%EA%F2%F0%EE%ED%ED%FB%E5%F3%F7%E5%E1%ED%E8%EA%E8/%CC%E8%EA%F0%EE%EF%F0%EE%F6%E5%F1%F1%EE%F0%FB/%CC%E8%EA%F0%EE%EF%F0%EE%F6%E5%F1%F1%EE%F0%FB%20iu4/mk.iu4.bmstu.ru/str/coma.html Команда "DAA" выполняется после сложения или вычитания двух двоично-десятичных чисел (BCD - Binary Coded Decimal). Число в BCD-коде содержит в каждой тетраде (половине байта) значения от 0 до 9. После выполнения команды "DAA" содержимое аккумулятора будет содержать правильный BCD-код результата, и флаг переноса будет установлен соответствующим образом для выполнения следующей BCD-операции, например, если складываются два 16-разрядных числа (4 десятичных разряда). Команда "DAA" работает недостаточно корректно после выполнения вычитания. Микроконтроллер 8051 не даёт возможности определить отрицательное BCD-число, поэтому достаточно трудно произвести их вычитание. Эта команда не производит преобразование байта, представленного в шестнадцатеричном коде, в BCD-число. Насколько я понимаю, можно сложить два младших байта BCD чисел, выполнить DAA, потом сложить два старших байта с переносом, выполнить DAA и получится правильный результат.