Консультация № 178859
04.06.2010, 19:06
45.00 руб.
0 4 2
Здравствуйте уважаемые эксперты! У меня такой вопрос, точне нужна помощь. Задача такая вообщем, нужно реализовать на ассемблере программу, которая с клавиатуры 16-ричное двухзначное (восьмиразрядное) число, переводит его в 10-чное и 2-чное, а результат выводить на экран. Помогите пожалуйста. Я тут собрал из частей код но не смог оптимизировать

Приложение:
cod segment
assume cs:cod,ds:cod
org 100h
begin:
mov dx,offset Start
call Message
;Чтение из командной строки
mov bx,80h
xor cx,cx
mov cl,[bx]
; получение длинны
test cx,cx
jnz CommLineSet
mov dx,offset NoCmd
call Message
jmp Exit
CommLineSet:
; вставлем число в регистр dx
dec cx
cld
lea si,[bx+2]
xor dx,dx
PutNumbToAX:
; вставлем число в регистр ax
shl dx,4
lodsb
sub al,'0'
cmp al,9
jbe TransDone
sub al,('A'-'0')-10
TransDone:
or dl,al
loop PutNumbToAX
;Конвертируем в десетичную и выводим на экран
push dx
mov dx,offset ResPrompt
call Message
pop ax
mov cx,5
mov bx,10000
mov di,offset Symbols
GetDigit: ;процедура перевода в десятичную СС
xor dx,dx
div bx
add al,'0'
stosb
push dx
mov ax,bx
xor dx,dx
mov bx,10
div bx
mov bx,ax
pop ax
loop GetDigit
mov dx,offset Symbols
call Message
; Конвертируем в двоичную и выводим на экран
push dx
mov dx,offset ResPromptBin
call Message
pop dx
mov cx,16
;mov di,offset SymbolsBin
GetBin: ; процедура перевода в двоичную СС
xor ax,ax
shl dx,1
adc al,'0'
stosb
loop GetBin
mov dx,offset SymbolsBin
call Message
Exit: ; Выход
mov dx,offset Finish
call Message
retn
Message: ;процедура вывода на экран
mov ah,09h
int 21h
retn


Start db 'Start !',0ah,0dh,'$'
NoCmd db 'No specified symbols in CMD !',0ah,0dh,'$'
ResPrompt db 'Result in digit:','$'
ResPromptBin db 'Result in bin:','$'
Symbols db '?0',0ah,0dh,'$'
SymbolsBin db '?00000b',0ah,0dh,'$'
Finish db 'Finish!',0ah,0dh,'$'
cod ends
end begin

Обсуждение

Неизвестный
04.06.2010, 22:29
общий
это ответ
Здравствуйте, Артем Борисовский.

В приложении - исправленная программа. Замечания помечены ;!
Ваша программа рассчитана не только на 2-значные, но и на 16-ричные числа до 4-х значащих цифр. Буквы должны быть в верхнем регистре.
Преобразование в 10-тичную и 2-ичную системы правильное, но слишком маленькие буфера для результатов. Кроме того, перед преобразованием в 2-ичную систему число уже было утеряно.
Чуток поправил сообщения.

Работу программы проверил.

Успехов!

Приложение:
cod segment
assume cs:cod,ds:cod
org 100h
begin:
mov dx,offset Start
call Message
;Чтение из командной строки
xor cx,cx
; mov bx,80h
; mov cl,[bx] ;! в принципе, это правильно, но излишне
mov cl,byte ptr DS:[80h] ;! проще (и на байт короче) так
;! DS: добавляем, чтобы TASM распознал 80h как адрес
; получение длины
test cx,cx
jnz CommLineSet
mov dx,offset NoCmd
call Message
jmp Exit

CommLineSet:
; вставлем число в регистр dx
dec cx
cld
; lea si,[bx+2] ;! для Вашего кода это было правильно
mov si,82h ;! так проще
xor dx,dx

PutNumbToAX:
; вставлем число в регистр ax
shl dx,4
lodsb
sub al,'0'
cmp al,9
jbe TransDone
sub al,('A'-'0')-10
TransDone:
or dl,al
loop PutNumbToAX

;Конвертируем в десятичную и выводим на экран
push dx ;! сохраняем для последующего перевода в двоичную систему
push dx
mov dx,offset ResPrompt
call Message
pop ax
mov cx,5
mov bx,10000
mov di,offset Symbols

GetDigit: ;процедура перевода в десятичную СС
xor dx,dx
div bx
add al,'0'
stosb
push dx
mov ax,bx
xor dx,dx
mov bx,10
div bx
mov bx,ax
pop ax
loop GetDigit
mov dx,offset Symbols
call Message

; Конвертируем в двоичную и выводим на экран
;! push dx - нужно было поместить в стек раньше, здесь DX = offset Symbols
mov dx,offset ResPromptBin
call Message
pop dx
mov cx,16
mov di,offset SymbolsBin
GetBin: ; процедура перевода в двоичную СС
xor ax,ax
shl dx,1
adc al,'0'
stosb
loop GetBin
mov dx,offset SymbolsBin
call Message
Exit: ; Выход
mov dx,offset Finish
call Message
xor ah,ah ; ждем нажатия любой клавиши (чтобы увидеть результат,
int 16h ; прежде чем консоль в Windows закроется)
retn

Message: ;процедура вывода на экран
mov ah,09h
int 21h
retn


Start db 'Start !',0ah,0dh,'$'
NoCmd db 'No specified symbols in CMD !',0ah,0dh,'$'
ResPrompt db 'Result in decimal: $'
ResPromptBin db 'Result in bin: $'
Symbols db 5 dup ('0'),0ah,0dh,'$' ;! 5 символов для десятичного числа
SymbolsBin db 16 dup('0'), 'b',0ah,0dh,'$' ;! 16 символов для двоичного числа
Finish db 'Finish! Press any key to exit...',0ah,0dh,'$'
cod ends
end begin
5
Неизвестный
04.06.2010, 22:35
общий
Артем Борисовский:
В программе число не вводится с клавиатуры, а передается в командной строке, Вы сами пометили это в комментариях.
Неизвестный
05.06.2010, 00:03
общий
Спасибо большее за помощь!
давно
Посетитель
7438
7205
05.06.2010, 00:08
общий
это ответ
Здравствуйте, Артем Борисовский.
Моя версия подправленной программы.
Вводит 1 байт, не более 2 hex-цифр из командной строки.
Добавил проверку на ошибки: проверяются символы на корректность, число цифр
Поменял вывод десятичного числа.
Код:
cod	segment 
assume cs:cod,ds:cod
org 100h
begin:
mov dx,offset Start
call Message
;Чтение из командной строки
mov bx,80h
; получение длины
xor cx,cx
mov cl,[bx]
jcxz ErrorNoCmd ;проверим на ноль - ничего не задано
; вставлем число в регистр dx
dec cx
cmp cx,2 ;ждем 1 или 2 hex цифры!
ja ErrorBigCmd ;если больше, то ошибка
lea si,[bx+2]
xor dx,dx
PutNumbToDX:
; вставляем число в регистр dx
shl dx,4
lodsb
or al,20h ;чтобы буковки 'a' и 'A' стали одинаковыми - 'a'
;на цифры не влияет!
sub al,'0'
jc ErrorNum ;<'0' - ошибка
cmp al,9
jbe TransDone ;'0'-'9' - ok
sub al,('a'-'0')-10
jc ErrorNum ;'9'-'a' - ошибка
cmp al,0fh
ja ErrorNum ;>'f' - ошибка
TransDone:
or dl,al
loop PutNumbToDX

;Конвертируем в десятичную и выводим на экран
push dx
mov dx,offset ResPrompt
call Message
pop ax ;в ax число
mov bx,10 ;будем делить на 10
mov di,offset Symbols ;буфер для числовой строки
xor cx,cx ;будем считать
push ax ;сохраним для дальнейшего преобразования в двоичный код
GetDigit: ;процедура перевода в десятичную СС
xor dx,dx
div bx ;остаток - очередная младшая цифра
push dx ;сохраним в стеке
inc cx ;считаем
test ax,ax ;пока что-то есть
jnz GetDigit
PutDigit: ;выводим в обратном порядке
pop ax
add al,'0'
stosb
loop PutDigit ;по всем цифрам
call PrintNum ;дооформим строку и выведем
; Конвертируем в двоичную и выводим на экран
mov dx,offset ResPromptBin
call Message
pop dx ;наше число
mov cx,8 ;8 бит
mov di,offset Symbols ;в том же буфере
GetBin: ; процедура перевода в двоичную СС
xor ax,ax
shl dl,1 ;у нас байт, с ним и работаем
adc al,'0'
stosb
loop GetBin
mov al,'b' ;добавим в конце 'b'
stosb
call PrintNum ;дооформим строку и выведем
Exit: ; Выход
mov dx,offset Finish
jmp Message

;ошибки
ErrorNoCmd: ;без параметра
mov dx,offset NoCmd
jmp Message
ErrorNum:
mov dx,offset ErrNum;не hex-число
jmp Message
ErrorBigCmd:
mov dx,offset BigCmd;больше 2-х цифр
jmp Message
PrintNum: ;вывод числовой строки
mov ax,0d0ah ;добавим перевод строки
stosw
mov al,'$' ;добавим '$' для функции 9
stosb
mov dx,offset Symbols
Message: ;процедура вывода на экран
mov ah,09h
int 21h
retn

Start db 'Start !',0ah,0dh,'$'
NoCmd db 'No specified symbols in CMD !',0ah,0dh,'$'
BigCmd db 'Many symbols in CMD! Must be two symbols',0ah,0dh,'$'
ErrNum db 'Not hex number!',0ah,0dh,'$'
ResPrompt db 'Result in digit: ','$'
ResPromptBin db 'Result in bin: ','$'
Symbols db 16 dup (?)
Finish db 'Finish!',0ah,0dh,'$'

cod ends
end begin
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Форма ответа