Связь с администрацией сайта:       

demo

Среди толпы я одинок

Глава 17 - практика:ввод чисел и системы счисления

Ввод чисел

Ввод числовой информации в ассемблерную программу обычно осуществляется в два этапа:

1)      ввод строки содержащей число;

2)      перевод строки в число.

Ввод строк рассматривался в предыдущих практических работах.

 

Для разработки алгоритма перевода введенной строки в число проанализируем структуру числа в позиционной системе счисления (в такой системе счисления вес цифры определяется ее местоположением в числе):

 

2398=2*1000+3*100+9*10+8=2*103+3*102+9*101+8*100

 

Таким образом, для перевода строки в число из введенной строки «2398» необходимо последовательно выделять цифры и производить суммирование произведений этих цифр и множителей соответствующих позиции цифры в числе. Если буфер для ввода строки был организован, например, следующим образом:

 

BUF  05,00,05 DUP (?)

 

то после ввода строки «2398» он будет выглядеть (в шестнадцатеричной системе счисления) так:

 

05,04,32,33,39,38,0d

 

где первый байт – размер буфера, второй – количество введенных симво-лов (без завершающего символа CR), третий, четвертый, пятый, шестой и седьмой – коды символов «2», «3», «9», «8» и «CR» соответственно. Легко заметить, что для того, чтобы из кода цифры получить саму цифру необхо-димо из соответствующего кода вычесть 30h (шестнадцатеричный код нуля). Затем, последовательно в цикле (второй байт – количество введенных символов) выбирая цифры, формировать соответствующий множитель, вычислять произведение и производить суммирование. Нижеследующий фрагмент программы иллюстрирует описанный алгоритм (символы рассматриваются справа налево).

 

;Ввод числа в виде строки

MOV         AH,0AH    ;в AH номер функции

LEADX,BUF     ;DS:DX адрес буфера для ввода

INT   21H

;Перевод строки в число, результат в DI

MOV         DI,0

LEABX,BUF+1;в BX адрес второго элемента буфера

MOV         CX,[BX]    ;в CX количество введенных символов

XORCH,CH

MOV SI,1  ;в SI множитель

MET: PUSH SI  ;сохраняем SI (множитель) в стеке

MOV         SI,CX         ;в SI помещаем номер текущего символа

MOV         AX,[BX+SI];в AX помещаем текущий символ

XORAH,AH

POP SI       ;извлекаем множитель (SI)из стека

SUB  AX,30H     ;получаем из символа (AX) цифру

MUL SI     ;умножаем цифру (AX)на множитель (SI)

ADDDI,AX        ;складываем с результирующим числом

MOV         AX,SI         ;помещаем множитель (SI) в AX

MOV         DX,10

MUL DX   ;увеличиваем множитель (AX) в 10 раз

MOV         SI,AX         ;перемещаем множитель (AX) назад в SI

LOOP MET        ;переходим к предыдущему символу

 

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

В большинстве случаев перевод из одной системы счисления в дру-гую осуществляется последовательным делением, в нашем случае, при переводе из десятичной системы счисления в двоичную, восьмеричную и шестнадцатеричную алгоритм можно значительно упростить, заменив деление сдвигом.

Перевод из десятичной системы счисления в двоичную осуществляется последовательными сдвигами на один бит вправо. Таким образом, значение очередного бита можно вычислить, проанализировав флаг переноса CF (если CF=1 то анализируемый бит был равен 1, и если CF=0, то анали-зируемый бит – 0).

Перевод из десятичной системы счисления в восьмеричную осуществляется последовательными сдвигами на три бита вправо. После очередного сдвига все биты кроме трех младших обнуляются (например, наложением маски командой AND). Таким образом, в регистре получается восьмеричная цифра, для получения ее символьного отображения к значению в регистре необходимо прибавить код нуля (30h).

Перевод из десятичной системы счисления в шестнадцатеричную осуществляется последовательными сдвигами на четыре бита вправо. После обнуления всех битов кроме четырех младших в регистре получается десятичный эквивалент шестнадцатеричной цифры (число от 0 до 15). Для его представления в шестнадцатеричной символьной форме необходимо организовать таблицу соответствия, которая в простейшем случае пред-ставляет собой следующую строку «0123456789ABCDEF». При перекодировании значение десятичного эквивалента используется как смещение в таблице относительно ее начала (перекодировка может осуществляться при помощи команды XLAT).

 

Разбор программы

Задание: разработать программу перевода чисел из десятичной системы счисления в двоичную, восьмеричную и шестнадцатеричную. Числа должны вводиться в десятичной системе счисления, а выводятся – в двоичной, восьмеричной и шестнадцатеричной.

Прога получилась большая! кроме всего прочего в ней показано как работать с файлами в DOS, а также показано как описывать процедуры, сама по себе программа очень простая, всё понятно из коментариев. Работу с файлами мы рассмотрим далее, а здесь она только для примера.

Файл perevod.asm

.model tiny

.code

org 100h

start:

;выводим приглашение

mov dx,offset message3

mov ah,09h

int 21h

;вводим имя файла

mov ah,0Ah

mov dx,offset filename

int 21h

;получаем имя в буфере

mov si,2

mov di,0

mov cl,byte ptr [filename+1]

mov ch,0

lo:mov ah,filename[si]

mov buf[di],ah

inc di

inc si

loop lo

;перевод строки

mov dx,offset crlf

mov ah,09h

int 21h

call openfile;открываем файл

mov handle,ax

;выводим приглашение

mov dx,offset message1

mov ah,09h

int 21h

;вводим строку

mov ah,0Ah

mov dx,offset buffer

int 21h

;перевод строки

mov dx,offset crlf

mov ah,09h

int 21h

;перевод строки в число в регистре AX

xor di,di

xor ax,ax;ax текущее значение результата

mov cl,blen

xor ch,ch

xor bx,bx

mov si,cx;тут длина буфера

mov cl,10;тут множитель 10,для команды MUL

asc2bin:

mov bl,byte ptr bcontents[di]

sub bl,'0';вычитаем из цифры код нуля

jb ascer;если код цифры меньше чем код '0'

cmp bl,9;или больше чем код '9'

ja ascer

mul cx

add ax,bx

inc di

cmp di,si;продолжать пока счетчик+1 меньше числа символов

jb asc2bin

;теперь число расположено в регистре ax

inc ax;действие над числом (ну произвольное, для примера :))

;начинаем вывод числа в hex формате

push ax

mov ah,9

mov dx,offset message2

int 21h

pop ax

push ax

mov si,0;это позиция в буфере который будем писать в файл

mov buf2out[si],'H'

inc si

mov buf2out[si],'E'

inc si

mov buf2out[si],'X'

inc si

mov buf2out[si],' '

inc si

mov bx,ax;теперь в bx число для вывода в dec формате

xchg ah,al;поместить в al старший байт

call print_al_hex

pop ax;восстановить в al младший байт

call print_al_hex

;начинаем вывод числа в dec формате

mov dx,offset crlf

mov ah,09h

int 21h

mov ah,9

mov dx,offset message4

int 21h

mov ax,bx

call print_al_dec

;пишем в файл

mov ah,40h

mov bx,handle

mov cx,si

lea dx,buf2out

int 21h

mov ah,3eh

mov bx,handle

int 21h

;конец программы

ret

ascer:

mov dx,offset errms

mov ah,9

int 21h

ret

;процедура вывода числа в al в hex формате

print_al_hex:

mov dh,al

and dh,0Fh;младшие 4 бита в dh

shr al,4 ;старшие 4 бита в al

call print

mov al,dh;теперь здесь младшие 4 бита

print:

cmp al,10;эти три команды переведут цифру в al в код ASCII, так круче чем XLAT!

sbb al,69h

das

mov dl,al

mov buf2out[si],dl

inc si

mov ah,2

int 21h

ret;этот ret работает два раза

;процедура вывода числа в ax в dec формате

print_al_dec:

mov buf2out[si],0Dh

inc si

mov buf2out[si],0Ah

inc si

mov buf2out[si],'D'

inc si

mov buf2out[si],'E'

inc si

mov buf2out[si],'C'

inc si

mov buf2out[si],' '

inc si

mov cx,10

xor bx,bx

m1:cmp ax,10

jb m2

xor dx,dx

div cx

or dl,30h

push dx

inc bx

jmp m1

m2:or al,30h

push ax

inc bx

mov cx,bx

lop:pop dx

mov buf2out[si],dl

inc si

mov ah,2

int 21h

loop lop

ret

;процедура открытия файла - описатель в ax

openfile proc

mov ah,3ch

mov cx,0

mov dx,offset buf

int 21h

jnc nerr

mov dx,offset myerr

mov ah,9

int 21h

;перевод строки

mov dx,offset crlf

mov ah,09h

int 21h

nerr: ret

endp

;!!!!!!!!!!!!!!!!!!!!!!!!!ОПИСАНИЕ ДАННЫХ ПРОГРАММЫ!!!!!!!!!!!!!!!!!!!!!!!!!!!

handle dw ?;это описатель файла!

buf db 8 dup (0),0

;это буфер который мы запишем в файл!

buf2out db 20 dup (?),'$'

message1 db "Decimal number: $"

message2 db "Heximal number: $"

message4 db "New dec number: $"

message3 db "Enter file name: $"

filename db 9,?,9 dup (0),0

errms db "Error number:programm terminate!!!!!!!!!!!!!$"

myerr db "WARNING!!! File not create$"

crlf db 0Dh,0Ah,'$'

buffer db 6;максимальный размер для ввода числа

blen db ?;размер после ввода

bcontents: ;содержимое буфера числа за концом программы COM

end start

 

Компиляция:

c:\specprog\tasm\bin\tasm.exe perevod.asm

c:\specprog\tasm\bin\tlink.exe perevod.obj /t/x

 

Вот что получилось в результате:

 

Rate this item
(3 votes)
Login to post comments