Форум программистов, компьютерный форум, киберфорум
Assembler для начинающих
Войти
Регистрация
Восстановить пароль
Другие темы раздела
Assembler Определить представимо ли число в виде суммы 2х простых чисел https://www.cyberforum.ru/asm-beginners/thread54369.html
Определить представимо ли число содержащиеся в ячейке 0200 в в виде суммы 2х простых чисел. использовать подпрограмму того, что число простое
Assembler Лабораторка: адресация микропроцессорных систем, нужна помощь
по тем же причинам не могу составить программу заданную преподавателем... просто так же дал задание без всяких обьяснений и сказал завтра принести... очень надеюсь на Вашу помощь... 1.1. Составить...
Assembler Копирование из регистра в регистр
Есть xmm-регистр, в котором хранятся два вещественных числа 2-ой точности (double A,B ) xmm0 = (A,B ) Нужно скопировать эти числа в другой xmm-регистр, допустим xmm1, используя SSE2 интструкции так...
Assembler Количество тактов народ помогите написать программу, которая подсчитывает количество тактов процессора, которые нужны для команды ADD. Надо использовать RDTSC. Зарание спасибо https://www.cyberforum.ru/asm-beginners/thread54021.html
Assembler Вычислить значение выражения Y=[(A+B)*C]^3/D https://www.cyberforum.ru/asm-beginners/thread53972.html
Кароче началось у нас на 3 курсе программирование микропроцессоров, ну и тут мы столкнулись с ассемблером, учитель у нас попался ужаснейший, ничего не объясняет, говорит учите как хотите... ну и в...
Assembler Запись числа в файл
нужно прочитать файл и записать в другой файл в столбкик знаки аского кода и напротив сколько раз они встречаются в файле...... вприинципе файл я прочитал... строку извлек, думаю пощитать символы не...
В поле байт найти количество чисел, являющихся полными квадратами Assembler
В поле байт найти количество чисел, являющихся полными квадратами. Использовать подпрограмму проверки того, что число является полным квадратом. Никто не знает решение?
Assembler Не работает как надо: помогите решить задачу с матрицей Люди помогите решить задачу где нужно преобразовать матрицу так чтобы элемент новой матрицы был равен произведению элемента первой матрицы стоящего на этом месте на минимальный элемент этого столбца... https://www.cyberforum.ru/asm-beginners/thread53673.html
Assembler Переместить 10 байт и найти их сумму https://www.cyberforum.ru/asm-beginners/thread53568.html
Помогите пожалуйста решить задачу по Ассемблеру: Переместив область данных длиной 10 байт с адреса 16А0на 16В0, найти сумму всех чисел и занести в ячейку с адресом 19А3... Надеюсь есть добрые люди......
Assembler Вставка битовой строки Помогите пожалуйста с задачкой. Осуществить вставку битовой строки А длиной 4 бита в строку памяти B длиной 16 бит, начиная со второго бита. А=0101 b; B-номер студента по списку. Если кто чем... https://www.cyberforum.ru/asm-beginners/thread53378.html
Jin X
bndstx
5148 / 1629 / 188
Регистрация: 14.12.2014
Сообщений: 3,070
Записей в блоге: 11
Завершенные тесты: 3
04.02.2017, 21:01 0

Ввод и вывод чисел в различных системах счисления

04.02.2017, 21:01. Просмотров 137356. Ответов 9
Метки (Все метки)

Ответ

Преобразование 64-битного знакового числа в строку с использованием FPU (с помощью инструкции fbstp)

Написал несколько процедур для преобразования 64-битных знаковых чисел в строку с использованием FPU. Работа процедур основана на инструкции fbstp, которая записывает число в память в BCD-формате.
Для работы достаточно инструкций 286 процессора (или даже 8086, если удалить строку .286, однако я не рекомендую этого делать, т.к. код в этом случае неоправданно удлинится).

Привожу здесь 2 варианта процедур вывода 64-битного числа на стандартный вывод (обычно на экран) с помощью функции DOS ah=2/int 21h.

Итак, вариант вывода чисел размером не более 18 десятичных знаков (таковы ограничения работы инструкции fbstp), что примерно соответствует 61 биту (60 бит + знак) + пример использования:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
; ###############################################################################################################
; ## Преобразование 64-битных знаковых чисел в строку с использованием FPU - 2017 (c) Jin X                    ##
; ## Редакция, реализующая работу максимум с 18-знаковыми числами (что примерно соответствует 60-битам + знак) ##
; ###############################################################################################################
 
.model tiny
.286
.code
 
ifdef   ??Version               ; TASM
  smart
  locals
endif
 
.startup
 
        mov     si,offset Number
        call    FPUInt64Output  ; выводим число Number на стандартный вывод
        jc      @@Error         ; число с ошибкой?
    @@Finish:
        int     20h             ; выход из программы
    @@Error:
        mov     ah,9
        mov     dx,offset mError
        int     21h             ; выводим сообщение об ошибке
        jmp     @@Finish
 
; Преобразование 64-битного знакового числа, записанного по адресу SI, в строку с выводом на стандартный вывод (как правило, на экран; выводится не более 19 символов, включая знак минуса)
; Число должно содержать не более 18 десятичных цифр без учёта знака (т.е. меньше квинтиллиона по модулю, что по факту почти соответствует 60-битовому числу + знаковый бит)
; На выходе: флаг CF=0 в случае успеха, CF=1, если указано недопустимое число (больше 18 десятичных цифр), при этом ничего не выводится
FPUInt64Output  proc    c       ; не удаляйте слово 'c', иначе процедура работать не будет (не будет генерироваться пролог и эпилог)
local   BCD: tbyte              ; резервируем место в стеке для записи BCD-формата числа (при этом выполняется enter 10,0 или его эквивалент push bp + mov bp,sp + sub sp,10)
        fild    qword ptr [si]  ; читаем целое число по адресу si (если число записано в формате с плавающей запятой, fild нужно заменить на fld)
        fbstp   [BCD]           ; записываем число в BCD-формате во временную локальную переменную
        mov     ah,2            ; номер функции DOS для вывода символа на экран
        mov     dx,'0-'         ; dl = символ минуса (для вывода отрицательных чисел), dh = символ нуля (отсекаемый символ, чтобы отсекать ведущие нули, см. ниже)
        add     byte ptr [BCD+9],dl  ; последний записанный инструкцией fbstp символ (10-й по счёту) = 0, если число положительное; 80h, если отрицательное; 0FFh в случае ошибки
        jc      @@Exit          ; 0FFh+'-' > 255, произошёл перенос, ошибка! (CF=1)
        jns     @@NoSign        ; 0+'-' < 80h, знака нет
        int     21h             ; выводим минус (80h+'-' > 80h, знак есть)
    @@NoSign:
        mov     si,18/2         ; кол-во пар символов (9)
    @@Next:
        mov     bl,byte ptr [BCD+si-1]  ; bl = очередной байт (читаем в обратном порядке, т.к. старшие цифры инструкция fbstp записывает в старшие байты)
        mov     cx,2            ; кол-во цифр в 1 байте
    @@Ch:
        ror     bl,4            ; меняем местами старшую и младшую тетраду (половину байта из 4-х бит), т.к. старшая цифра записана в старшей тетраде
        mov     dl,bl           ; переносим цифру в dl
        and     dl,0Fh          ; оставляем только 4 младший бита регистра dl (удаляя цифру в старшей тетраде)
        add     dl,'0'          ; преобразуем цифру в символ
        cmp     dl,dh           ; если ещё не выведено ни одной цифры, dh = '0' (см. выше); таким образом, если ещё не было цифр или были только '0', а текущий символ тоже '0',
        je      @@NoOut         ; ...то не выводим его
        int     21h             ; иначе выводим (ah=2, dl=символ)
        mov     dh,-1           ; чтобы в следующий раз выводились любые символы (в т.ч. '0')
    @@NoOut:
        loop    @@Ch            ; выводим вторую цифру
        dec     si              ; уменьшаем смещение следующего байта
        jnz     @@Next          ; переходим к следующему символу, если смещение > 0
        test    dh,dh           ; был ли вывод хотя бы одного символа? (заодно устанавливаем CF=0)
        js      @@Exit          ; да (если dh=-1), переходим
        int     21h             ; иначе выводим ноль (ah=2, dl='0') - такая ситуация возникнет только если исходное число = 0
    @@Exit:
        ret                     ; выходим из процедуры (предварительно выполняется leave или его эквивалент mov sp,bp + pop bp)
FPUInt64Output  endp
 
.data
 
mError db       'Wrong number!',13,10,'$'
 
Number  dq      -1234567890775533
String  db      20 dup (?)
 
end
Усовершенствованный вариант вывода любых 64-битных чисел (ограничения инструкции fbstp ликвидируются предварительным вычислением старшей 19-й цифры с привидением числа к 18-знаковому) + пример использования:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
; ###############################################################################################################
; ## Преобразование 64-битных знаковых чисел в строку с использованием FPU - 2017 (c) Jin X                    ##
; ## Редакция, реализующая работу с любыми 64-битовыми числами (в т.ч. содержащими более 18 десятичных знаков) ##
; ###############################################################################################################
 
.model tiny
.286
.code
 
ifdef   ??Version               ; TASM
  smart
  locals
endif
 
.startup
 
        mov     si,offset Number
        call    FPUInt64Output  ; выводим число Number на стандартный вывод
 
        int     20h             ; выход из программы
 
; Преобразование 64-битного знакового числа, записанного по адресу SI, в строку с выводом на стандартный вывод (как правило, на экран; выводится не более 20 символов, включая знак минуса)
FPUInt64Output  proc    c       ; не удаляйте слово 'c', иначе процедура работать не будет (не будет генерироваться пролог и эпилог)
local   BCD: tbyte              ; резервируем место в стеке для записи BCD-формата числа (при этом выполняется enter 10,0 или его эквивалент push bp + mov bp,sp + sub sp,10)
        ; Поскольку инструкция fbstp может записать число в BCD-формате, состоящее максимум из 18 десятичных цифр, а 64-битное число может содержать ещё одну цифру, придётся выполнить ряд операций...
        fld     [Double1e18]    ; st(0) = 1e18 (квинтиллион, единица с 18 нулями)
        fild    qword ptr [si]  ; st(0) = целое число по адресу si (число должно быть записано как обычное целое, а не в формате с плавающей запятой), st(1) = 1e18
        mov     dx,'0-'         ; dl = символ минуса (для вывода отрицательных чисел), dh = символ нуля (отсекаемый символ, чтобы отсекать ведущие нули, см. ниже)
        test    byte ptr [si+7],80h  ; проверяем старший бит исходного числа
        jz      @@Chk1e18       ; если он сброшен, значит число положительное, прыгаем
 
        mov     ah,2            ; номер функции DOS для вывода символа на экран
        int     21h             ; выводим минус (ah=2, dl=символ)
        fchs                    ; меняем знак (преобразуем в положительное): st(0) = |st(0)|
        jmp     @@Chk1e18       ; переходим к сравнению числа с 1e18 (квинтиллионом)
    @@Sub1e18:
        inc     dx              ; увеличиваем dl на 1 (19-ю цифру)
        mov     dh,-1           ; dh = -1, чтобы в дальнейшем выводились все цифры (без удаления ведущих нулей)
        fsub    st(0),st(1)     ; st(0) = st(0)-st(1) = число-1e18
    @@Chk1e18:
        fcom                    ; сравниваем st(0) (число) с st(1) (1e18)
        fstsw   ax              ; получаем слово статуса FPU (результата сравнения)
        sahf                    ; сохраняем его во флагах
        jae     @@Sub1e18       ; если больше (число > 1e18), значит есть 19-й знак, прыгаем
 
        mov     ah,2            ; номер функции DOS для вывода символа на экран
        test    dh,dh           ; 19-я цифра не 0 (если она есть, dh=-1)?
        jns     @@No19          ; если 0, не выводим её
        add     dl,'0'-'-'      ; иначе преобразуем цифру в символ, добавив разницу между '-' и '0' (изначально мы прибавляли единицы к символу al='-')
        int     21h             ; и выводим его (ah=2, dl=символ)
    @@No19:
        fbstp   [BCD]           ; записываем число (не более 18 цифр) в BCD-формате во временную локальную переменную с удалением его из стека FPU, st(0) = 1e18
        fstp    st(0)           ; удаляем лишнее число (st(0)=1e18) из стека FPU
 
        ; Основной цикл вывода цифр
        mov     si,18/2         ; кол-во пар символов (9)
    @@Next:
        mov     bl,byte ptr [BCD+si-1]  ; bl = очередной байт (читаем в обратном порядке, т.к. старшие цифры инструкция fbstp записывает в старшие байты)
        mov     cx,2            ; кол-во цифр в 1 байте
    @@Ch:
        ror     bl,4            ; меняем местами старшую и младшую тетраду (половину байта из 4-х бит), т.к. старшая цифра записана в старшей тетраде
        mov     dl,bl           ; переносим цифру в dl
        and     dl,0Fh          ; оставляем только 4 младший бита регистра dl (удаляя цифру в старшей тетраде)
        add     dl,'0'          ; преобразуем цифру в символ
        cmp     dl,dh           ; если ещё не выведено ни одной цифры, dh = '0' (см. выше); таким образом, если ещё не было цифр или были только '0', а текущий символ тоже '0',
        je      @@NoOut         ; ...то не выводим его
        int     21h             ; иначе выводим (ah=2, dl=символ)
        mov     dh,-1           ; чтобы в следующий раз выводились любые символы (в т.ч. '0')
    @@NoOut:
        loop    @@Ch            ; выводим вторую цифру
 
        dec     si              ; уменьшаем смещение следующего байта
        jnz     @@Next          ; переходим к следующему символу, если смещение > 0
        test    dh,dh           ; был ли вывод хотя бы одного символа?
        js      @@Exit          ; да (если dh=-1), переходим
        int     21h             ; иначе выводим ноль (ah=2, dl='0') - такая ситуация возникнет только если исходное число = 0
    @@Exit:
        ret                     ; выходим из процедуры (предварительно выполняется leave или его эквивалент mov sp,bp + pop bp)
FPUInt64Output  endp
 
.data
 
Double1e18 dq   1.0e18          ; значение, используемое в процедурах
 
Number  dq      8000000000000000h  ; -9223372036854775808 (минимально возможное значение)
String  db      21 dup (?)
 
end
Кроме приведённых выше процедур для каждой из версий я сделал ещё по 2 процедуры: вывод на экран через int 29h и преобразование числа в строку без вывода на экран.
Всё это вы можете найти в прикреплённых исходниках, а также по ссылке: Преобразование 64-битных знаковых чисел в строку с использованием FPU
.

Вернуться к обсуждению:
Ввод и вывод чисел в различных системах счисления
1
Вложения
Тип файла: zip IntStr64FPU.zip (6.1 Кб, 9 просмотров)
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.02.2017, 21:01
Готовые ответы и решения:

Ввод и вывод чисел в различных системах счисления
здравствуйте. помогите разработать программу Разработать программу перевода ввода и вывода чисел в...

Ввод и вывод чисел в различных системах счисления, исправить код
.model small .stack 100h .data .code InputInt proc mov ah,0ah

Ввод символов и отображение в различных системах счисления
Здравствуйте, форумчане! Есть проблема, прошу подсказки. Нужно создать прогу на ассемблере,...

Организовать ввод значений в различных системах счисления
Всем привет, делаю калькулятор и есть некоторые трудности! В общем, шкодю в WPF ХAML C#, и пытаюсь...

9
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.