Adventurer #08
31 августа 1998

Обмен опытом - о том как оперировать в ассемблере с длинными числами типа Long.

      (C) Maximum/INTEGER

        LONG ??? Что это такое ?
     ─────────────────────────────

      Так  обозначаются  длинные числа на
PC и на AMIGA . Т. е это числа, лежащие в
диапазоне  от 0 до 4294967295, для предс-
тавления  которых  отводится  4  (четыре)
байта в памяти.
      В  данной статье я научу вас опери-
ровать  с  такими числами. И для чего это
надо? например, вы пишете игру, в которой
есть такие параметры,как деньги, золото и
т.  д.  Как  водится, денег в таких играх
бывает  намного  больше,  чем  65535. Вот
здесь-то как раз и пригодятся LONG цифер-
ки...
      Итак, у нас есть число 12. 000. 00.
В Long оно выглядит так: #00B71B00
      В ассемблере же стоит набирать так:
long_num DW #00B7, #1B00
      Формат задания любого Long числа:
      ...
      LD HL,#00B7
      EXX
      LD HL,#1B00
      ...
      Т.е в HL старшая  часть  числа, а в
HL' его младшая часть.

        Сложение двух Long чисел
      ────────────────────────────

      Надо  просто сложить младшие части,
а  потом с учетом флага C сложить и стар-
шие:
L_ADD
      ADD HL,DE
      EXX
      ADC HL,DE
      EXX
      RET
      На  входе  у  процедуры: HL и HL' -
первое число, в DE и DE' - второе число.
      На  выходе: HL и HL' сумма двух чи-
сел.
       Разность двух Long чисел
     ────────────────────────────


      Здесь примерно то же самое:
L_SUB
      AND A
      SBC HL,DE
      EXX
      SBC HL,DE
      RET
      Параметры такие же, как у L_ADD.

           Печать Long чисел
         ─────────────────────


      Для  печати числа нам нужно его пе-
рекодировать  из Long в ASCII коды, что и
делает следующая процедура:
L_PR      LD IX,L_TAB; см.ниже
          LD A,10    ; число из 10 знаков
L_PR0     EX AF,AF'
          EXX
          LD E,(IX+0); ст.слово из табл.
          LD D,(IX+1)
          EXX
          LD E,(IX+2); мл.слово из табл.
          LD D,(IX+3)
          LD A,'0'-1
L_PR1     CALL L_SUB ; отнимаем пока не
          INC A      ; включится флаг C
          JR NC,L_PR1;
          CALL L_ADD ; востановим число
          LD (BC),A  ; в буфер его
          INC BC
          INC IX
          INC IX
          INC IX
          INC IX
          EX AF,AF'
          DEC A
          JR NZ,L_PR0; все числа
          RET        ; ...

;таблица чисел:

L_TAB     DW #3B9A,#CA00 ; 1000000000
          DW #05F5,#E100 ; 100000000
          DW #0098,#9680 ; 10000000
          DW #000F,#4240 ; 1000000
          DW #0001,#86A0 ; 100000
          DW #0000,#2710 ; 10000
          DW #0000,#03E8 ; 1000
          DW #0000,#0064 ; 100
          DW #0000,#000A ; 10
          DW #0000,#0001 ; 1

   Перед  вызовом  в HL и HL' число, а в
BC адрес буфера для числа. Пример:

          ORG #6000
          LD HL,#FFFF
          EXX
          LD HL,#FFFF
          LD BC,BUFF
          CALL L_PR
          CALL 3435
          LD A,2
          CALL 5633
          LD HL,BUFF
          LD B,10
LOOP      LD A,(HL)
          RST 16
          INC HL
          DJNZ LOOP
          RET

BUFF      DS 10

             Ввод Long числа.
           ───────────────────


   Вернее не ввод, а преобразование числа
из ASCII кодов в Long формат. Применить
это можно так:

          ...
          LD HL,BUFF
          ...
          CALL INPUT ;Вводим число
          LD HL,BUFF
          CALL L_DC
          ...

   На входе у процедуры: HL-адрес буфера,
где сидит число:

BUFF      DB "212042067"
          DB 0           ;Маркер конца т.е
                         ;код <"0" и >"9"


   После вызова в HL и HL' будет число.

L_DC      PUSH HL
          LD B,0
L_DC1     LD A,(HL)   ;Подсчитаем сколько
          CP "0"      ;циферок у нашего
          JR C,L_DC2  ;числа
          CP "9"+1
          JR NC,L_DC2
          INC B
          INC HL
          JR L_DC1
L_DC2     EXX
          POP BC      ;в BC его
          LD HL,0     ;Обнулим
          EXX         ;новое
          LD HL,0     ;число
          EXX
L_DC3     LD A,B      ;все зделали ?
          LD DE,0-4
          AND A
          RET Z       ;нееет !
          EXX
          DEC A        ;используя таблицу
          LD IX,L_TAB+36
          JR Z,L_DC4  ;найдем
          ADD IX,DE   ;нужный
          DEC A       ;нам
          JR Z,L_DC4  ;разряд
          ADD IX,DE   ;числа
          DEC A
          JR Z,L_DC4
          ADD IX,DE
          DEC A
          JR Z,L_DC4
          ADD IX,DE
          DEC A
          JR Z,L_DC4
          ADD IX,DE
          DEC A
          JR Z,L_DC4
          ADD IX,DE
          DEC A
          JR Z,L_DC4
          ADD IX,DE
          DEC A
          JR Z,L_DC4
          ADD IX,DE
          DEC A
          JR Z,L_DC4
          ADD IX,DE
L_DC4     DEC B       ;ага, нашли
          LD E,(IX)   ;берем то что
          LD D,(IX+1) ;мы будем
          EXX         ;прибавлять
          LD E,(IX+2)   LD D,(IX+3) ;новому числу
          LD A,(BC)   ;какое у вас число ?
          INC BC
L_DC5     CP "0"      ;пока не "ноль"
          JR Z,L_DC3
          CALL L_ADD  ;прибавляем разряд
          DEC A
          JR L_DC5

      Ну  все, я дал уже достаточно много
информации  про Long, так что пользуйтесь
на здоровье...
      Надеюсь,  что данная статья кому-то
поможет.  Еще  хочу напомнить, что такими
числами  уже  успешно воспользовался всем
известный  Слава  Медноногов в своей UFO.
Больше  я  такого  метода  пока  нигде не
встречал.

                  * * *





Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
CPU для Вас - Работа с TR-DOS на уровне машинных кодов.
Информбюро - Что читать, и где читать?...
Top 13 - Наша дюжина.

В этот день...   24 сентября