0

我的汇编代码有问题。我想将 AF 之间的用户输入字符转换为它们各自的十进制数字。

样本输出:

从 AF 输入一个字符:B 十进制为 11。

我无法处理转换。请帮助我。谢谢这是代码

.model small
.stack 100h
.data
        msg1 db 'Enter a character from A_F:$ '
        msg2 db 'In decimal it is:$'
        char db ?
.code
MAIN PROC
        mov ax,@data
        mov ds,ax

        mov ah,09h                ;Displaying msg1
        mov dx,offset msg1
        int 21h
        mov ah,01h                ;Taking input
        int 21h
        mov char,al

        mov ah,2                    ;For go to next line
        mov dl,0dh
        int 21h
        mov dl,0ah
        int 21h                        ;Displaying msg2
        mov ah,09h
        mov dx,offset msg2
        int 21h                
        mov ah,02h          ;converting character   
        sub char,30h
        mov dl,char
        int 21h

        mov ah,4ch
        int 21h
MAIN ENDP
END MAIN
4

1 回答 1

0

所以你可以作弊,只需要一个查找表(还有一个更简单的作弊方法)。但正确的方法是做数学。您必须从基数 2 或技术上的基数 16 转换为基数 10。Tou 可以轻松地从基数 2 移动到基数 8(八进制)再到基数 16(十六进制),只需位操作,因为 8 和 16 是 2 的幂。但是 10不是 2 的幂,你不能用位操作来做到这一点。

我们更熟悉的是时基 60 时分秒。1 小时 60 分钟 一分钟 60 秒 那么 4321 秒是多少小时?你怎么解决的?一小时有多少秒?60*60 = 3600 对吧?两小时是 7200 秒,所以 4321 介于 1 和 to 之间,确切地说是 4321/3600 或 1 余数 721。或 1 小时 721 秒。721秒是多少分钟?721/60 = 12 余数 1 所以 4321 秒是 1 小时 12 分 1 秒。仅用于检查 3600*1 + 12*60 + 1 = 4321。或 (60^2)*1 + (60^1)*12 + (60^0)*1 - 4321。

0x1234 到十进制呢?我们的计算器告诉我们 4660。简短的答案是按 10 的幂向下计算,等于或高于该数字。所以 16 位数字不能大于 65535 所以第 10000 位或 10^4。0x1234 / 10000 = 0 余数 0x1234。取余数 0x1234 / 1000 = 4 余数 0x294 (660), 取余数 0x294 / 100 = 6 余数 0x3C (60), 取余数 0x3C / 10 = 6 余数 0, 取余数 0 / 1 = 0. 全部抓取商 04660 所以答案是十进制的 4660。

所以字母 B 是 ascii 数字 0x42,小写 0x62 所以你必须小心。0x42 - 0xB = 0x37。

因此,从 ascii 字符 0-9 中减去 0x30 会得到数字 0 - 9。但如果您知道/假设这是一个(十六进制)数字并且大于 0x39,则改为减去 0x37。0x42 - 0x37 = 0xB,0x62 - 0x37 = 0x2B,您可以使用 0xF 并清理大写和小写。

4 位的最大数是 15,因此要将基数 2/16 转换为基数 10,我们只需要处理 10^1 和 10^0。所以 0xB / 10 = 1 余数 1 1/1 = 1,取商 0xB = 11 十进制。

这里最简单的作弊方法是,如果您的输入限制在 0xA 和 0xF 之间,即 10 到 15。您知道所有除以 10 的数字都是 1 余数 0 到 5。所以只需减去 10,就可以得到 0 到 5。

下一个问题,您将取 0x42(字符 B)并减去 0x30,即 0x12,ascii 图表上的设备控制一个基本上没有意义尝试使用 int21 ah = 2 与该字符。要打印出数字 11,您需要先打印一个 0x31,然后再打印一个 0x31。如果您的输入是 F,则答案是 15,您发送一个 0x31 和一个 0x35。作弊是取0x46你的输入('F'),减去0x37得到0xF,然后减去10得到0x5,打印10的0x31,然后将0x30加到0x5得到0x35并打印出来。您可以将 0x37 和 10 减法组合到 0x41。

'A' = 0x41,  0x41 - 0x41 = 0x00, 0x00+0x30 = 0x30 = '0'
'B' = 0x42,  0x42 - 0x41 = 0x01, 0x01+0x30 = 0x31 = '1'
'C' = 0x43,  0x43 - 0x41 = 0x02, 0x02+0x30 = 0x32 = '2'
'D' = 0x44,  0x44 - 0x41 = 0x03, 0x03+0x30 = 0x33 = '3'
'E' = 0x45,  0x45 - 0x41 = 0x04, 0x04+0x30 = 0x34 = '4'
'F' = 0x46,  0x46 - 0x41 = 0x05, 0x05+0x30 = 0x35 = '5'

甚至更优化您的特定输入限制

'A' = 0x41, 0x41 - 0x11 = 0x30 = '0'
'B' = 0x42, 0x42 - 0x11 = 0x31 = '1'
'C' = 0x43, 0x43 - 0x11 = 0x32 = '2'
'D' = 0x44, 0x44 - 0x11 = 0x33 = '3'
'E' = 0x45, 0x45 - 0x11 = 0x34 = '4'
'F' = 0x46, 0x46 - 0x11 = 0x35 = '5'

您可能想要限制检查,如果输入字符小于 0x41 或大于 0x46 可能会输出一个“?” (0x3F) 而不是数字响应。

所以你的转换在两个方面是错误的,首先你忘记了输出 10 到 15 之间的数字需要两个字符。其次你的数学结果需要是一个有意义的字符(在 0x30 和 0x35 之间)

于 2015-11-07T04:55:08.820 回答