Печать упакованного BCD (DT) - язык ассемблера (TASM)

Попробовал сделать простой калькулятор на ассемблере. Я использовал TASM (школьная политика). Проблема заключается в печати числа, сохраненного с помощью команды FBSTP (команды сопроцессора) в переменной DT.

FBSTP adr - Сохраняет по адресу «adr» значение, расположенное на вершине стека (ST (0)) в виде упакованного десятичного числа (определено по адресу «adr» с помощью DT). Указатель стека уменьшается. Преобразование выполняется в процессе хранения.

Я отлаживал программу, и при делении на 10 результат искажается. Например: 12*1=12. Результат в res2 правильный. После перемещения в AX это все еще правильно, но когда я делю его на 10, DX становится 8 вместо 2, поэтому вместо 12 он печатает 18. Я также заметил, что 12h = 18d, но я не могу установить связь. Л.Э.: Если я использую простое целочисленное хранилище в текстовой переменной и печатаю ее, все работает нормально.

Вот часть кода, которая, как мне кажется, имеет значение:

multiplication:
FINIT
FILD x
FILD y
FMUL
FBSTP res2
FWAIT
MOV ax,WORD PTR res2
call write
jmp_line
jmp exit  


write       PROC    NEAR ;my printing proc moves cursor x spaces and starts writing
                          from back to front

    PUSH    DX
            PUSH    AX
    PUSH    CX
    MOV     CX,0

    CMP     AX, 0;check sign
    JNS     ok_write
    NEG     AX ;negate if <0
    MOV     CX,1 ;used to know if number is negative


ok_write:
    printspace ;macro that jumps 5 spaces(maximum number length)
    ;starts printing the number backwards
    print_digit:
    inc len
    ;print each digit
    MOV DX,0 ;prepare DX for storing the remeinder
    DIV CS:ten ;divide AX by 10 so that the last digit of the number is stored
    ADD dl,30h ;transform to ascii
    PUSH AX ;save AX
    MOV ah,02h
    INT 21h  ;print last digit
    printchar   8 ;put cursor over last printed digit
    printchar   8 ;move cursor in front of last printed digit

    cmp divi,1  ;
    JNE not_div
    cmp len,1
    JNE not_div
    printchar '.'
    printchar   8
    printchar   8

    not_div:
    POP AX ;retreive AX
    CMP AX,0 ;when AX=0 the number is written
    JNE print_digit
    ;/print each digit
    CMP     CX,1
    JNE     end_print
    printchar   '-'
   end_print:

    POP     CX
    POP     AX
    POP     DX
    RET
  write       ENDP  

Большое спасибо.


person Vlad Topala    schedule 05.02.2012    source источник
comment
Я не анализировал весь код, который вы разместили, но вот что странно: DIV CS:ten. Если ten находится в сегменте данных, а CS не совпадает с DS, вы можете делить на что-то другое, чем ten. Попробуйте разделить на регистр, предварительно загруженный на 10, например. mov si, 10+div si.   -  person Alexey Frunze    schedule 30.03.2012


Ответы (1)


Вы загружаете число BCD в AX. BCD означает двоично-десятичный код. поэтому каждые 4 бита на самом деле являются десятичным значением. Делишь на 10, тоже десятичное. Но AX обрабатывает числа как шестнадцатеричные. Если вы попытаетесь разделить 12 (bcd) на 10 (десятичное), то 12 будет рассматриваться как шестнадцатеричное, а десятичное значение равно 18. 18 разделить на 10 (десятичное) или 0Ah действительно дает в конце 18 десятичное. Если 12 — это bcd, вам нужно только преобразовать упакованный bcd (каждые 4 бита — это десятичное число, закодированное в шестнадцатеричном формате) в неупакованный (каждые 8 ​​бит представляют одну десятичную цифру). Чтобы упростить задачу: если AX содержит 12 (bcd), то вы можете использовать AX с 0Fh, чтобы получить из него 2, и ax с 0F0h, чтобы получить из него 1. Для цифр вы просто добавляете к нему 30h ("0"). Для палаток вы сокращаете 4 бита и добавляете к ним 30h ("0"). Еще раз: если вы преобразуете упакованный BCD в AX = 12 в распакованный BCD в AX = 0102 и добавите к нему 3030h, AX будет содержать ASCII 12 (bcd). Чтобы сохранить это для печати на экране, вы должны знать, что младшие 8 бит будут храниться в младших адресах в памяти. Поэтому swith AH и AL с xchg AH, AL таким образом AX = 3231h и сохранить в ячейке памяти в DS. Для чисел, превышающих 99 (BCD), вы должны использовать ту же технику для извлечения сотен, тысяч и т. д. Я надеюсь, что это прояснит ситуацию.

person Agguro    schedule 16.02.2015