8086大会(TASM):显示一个ASCII字符值作为十六进制 [英] 8086 Assembly (TASM): Displaying an ASCII character value as HEX

查看:252
本文介绍了8086大会(TASM):显示一个ASCII字符值作为十六进制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

**编辑澄清和干净code。

我试图接受来自键盘的字符(任何字符)和它的ASCII值转换为十六进制,然后显示它。

我知道如何从基数10转换为十六进制,但只是为了确保我没有使用不正确的术语:

如果我在我的ASCII值输入C,它的十进制值是63。63除以16(十六进制为基数为16)= 3.9375。保存3的商供以后使用。余*碱(0.9375 * 16)= 15。图15是十六进制字符F。

由商基座(3/16)= 0.1875分。商为0,因此这是在转换的最后一步。其余*基地(1875 * 16)= 3

从上阅读他们第一个(先入后出,如果想着堆栈),我也得到3F作为十进制数63(十六进制值,它是ASCII码为C )

这是正确的,是吗?

这是pretty简单的阅读,我希望。我刚刚得到的键盘(AL)的特点,集BX为除数(基数为16),然后除以BX AL,存储栈中的剩余部分,​​后来通过在堆栈中环路,并尝试以显示它..

我想我的问题是,什么是错我的乘法和我INT 21H / 02H。我不知道如果我需要,以显示字符或加30H不...

在最重要的是,我甚至不知道我需要在这一点上(显示),但无论如何,因为我还没有想出如何10-15转换为A-F十六进制。

我试着与我的老师来说,等待30分钟后让他把话说完学生的另一个鹅群在我的课(约从另外一个他的课,而不是这个东西......这激怒了我相当位),我得到了最是从头再来。

当问及关于使用SHR和SHL什么?因为它指出了我,但我被告知,它可以在不认为做,而且我不能使用这些命令(他们没有被覆盖的类)。

这是我做错了任何输入?谢谢!

  CHAR2HEX PROC;接受一个字符,打印的十六进制ASCII值。        MOV DX,OFFSET AskChar;显示提示
        MOV AH,09H
        INT 21H        MOV AX,0;清除AX        MOV AH,07H;获取键盘输入瓦特/无回声(AL)
        INT 21H        MOV BX,16;设置除数(基16)
        MOV CX,0;初始化计数器
        MOV DX,0;清除DX        划分:
                                    ;股息(什么是被分割)的DX / AX对,在商AX,剩余的DX。
            DIV BX;除(将字大小)。
            PUSH AX;保存DX(其余的)堆栈。            ADD CX,1;添加一个反击            MOV DX,0;清除余(DX)
            CMP AX,0;比较商数(AX)为零
            JNE鸿沟;如果AX不为0,进入鸿沟        乘:
                                    ;乘余数(从堆栈)16来获得十六进制值。
            MOV DX,0;清除DX
            POP AX;从获得剩余堆栈到AX。            MUL BX;乘AX * BX。 (DX =高位,AX =低位)
            MOV DX,AX            SUB DL,30H; ADD 30H到DL
            MOV AH,02H; 02H显示AH(DL)
            INT 21H;发送到DOS            LOOP乘;如果更多的工作要做,再乘以
                                    ; LOOP从CX减1。如果不为零,循环。
            RET
    CHAR2HEX ENDP
年底动工

的EDITED **

我终于得到它!我能得到程序返回已在键盘上推的ASCII字符的十六进制值,但前提是每个余数是0到9这不会到F显示了A的工作,而是用冒号,分号等...

我看着一个ASCII / Deicmal /六角图网上,并注意到字符0到9 30H 39H通过。但字符A(十六进制10)不启动,直到40H。所以我改变了计划,这样,如果该值大于39H时,将其添加到7H DL,然后显示它。

  CHAR2HEX PROC;接受一个字符,打印的十六进制ASCII值。        MOV DX,OFFSET AskChar;显示提示
        MOV AH,09H
        INT 21H        MOV AH,07H;获取键盘输入瓦特/无回声(AL)
        INT 21H        MOV CL,AL;复制用户输入(AL)到CL
        MOV AX,0;清除AX(摆脱HO位)
        MOV AL,CL;复制用户输入回AL        MOV BX,16;设置除数(基16)
        MOV CX,0;初始化计数器
        MOV DX,0;清除DX        DIV2:
                                    ;股息(什么是被分割)的DX / AX对,在商AX,剩余的DX。
            DIV BX;除(将字大小)。
            PUSH DX;保存DX(其余的)堆栈。            ADD CX,1;添加一个反击
            MOV DX,0;清除余(DX)
            CMP AX,0;比较商数(AX)为零
            JNE Div2的;如果AX不为0,进入Div2的:        getHex2:
            MOV DX,0;清除DX。
            POP DX;把堆栈顶部到DX。
            ADD DL,30H;转化率字符。            CMP DL,39H
            JG MoreHex2        HexRet2:            MOV AH,02H; 02H显示AH(DL)
            INT 21H;发送到DOS            LOOP getHex2;如果更多的工作要做,再次getHex2
                                    ; LOOP从CX减1。如果不为零,循环。
            JMP SKIP2
        MoreHex2:
            ADD DL,7H
            JMP HexRet2;返回其添加7H之前离开的地方。
        SKIP2:
            RET
    CHAR2HEX ENDP


解决方案

您为基数10的转换逻辑看起来很不错:每个其余由10分会给你一个数字,他们会从最低显著位数的订购最显著的,所以你需要打印前扭转所得数字。他们推到堆栈,完成后会做一个很好的和紧凑的方式换弹出他们。

有关转换为十六进制时,操作是相同的:除以16,得到的余数,反向,并打印。但是,也有几点需要注意:除数16右移4位。余数是值和0FH ,所以你实际上并不需要任何算术运算。移位和操作就足够了。此外,你甚至都不需要涉及到堆栈。您可以从最显著半字节(四位)到最低显著之一进行,并且打印为你计算它们。你似乎第二件事与一个半字节转换为十六进制数字挣扎。只需添加 30小时是不够的。它是小数不够好,但对于十六进制值,你已经得到了数10〜15为好。这些都需要被添加到 41H (ASCII中的'A')减去10来代替。或者,你可以通过你要打印的半字节的值,把数字'0'到'9'和'A'到'F'在一个表和索引他们。

您可能还需要编写一个程序,将来自输入读取一个数字。阅读每一个数字,直到你读一个换行符,转换成字符十进制值,并更新蓄能器,将让你读过的数量。您将需要使用此为十六进制和十进制输出功能。

** Edited for clarification and "cleaner" code.

I'm trying to accept a character from the keyboard (any character) and convert it's ASCII value to hex, then display it.

I know how to convert from base 10 to hex, but just to make sure I'm not using incorrect terminology:

If I enter "c" in as my ASCII value, it's decimal value is 63. 63 divided by 16 (hex is base 16) = 3.9375. Save the quotient of 3 for later. Remainder * base (.9375 * 16) = 15. 15 is Hex character "F".

Quotient divided by base (3 / 16) = 0.1875. Quotient is zero, so this is the last step in conversion. Remainder * base (.1875 * 16) = 3

Read them from last to first ("first in, last out", if thinking about the stack), and I get "3F" as the Hex value for the decimal number "63" (which is ASCII for "c")

This is correct, yes?

It's pretty simple to read, I hope. I just get the character from the keyboard (AL), set BX as the divisor (base 16), and then divide AL by BX, store the remainder in the stack, and later on loop through the stack and try to display it...

I think my problem is that something is wrong with my multiplication and with my INT 21H/02H. I'm not sure if I need to add 30h in order to display the character or not...

On top of that, I'm not even sure if I need to be at that point (displaying) yet anyway, because I still haven't figured out how to convert 10-15 to A-F for hex.

I tried speaking with my teacher, and after waiting 30 minutes for him to finish speaking to another gaggle of students in my class (about something from another one of his classes, and not this one...which irked me quite a bit), the most that I got was "start over".

When asked about "what about using SHR and SHL?" as it was pointed out to me, but I was told that it can be done without that, and that I can't use those commands (they haven't been covered in the class).

Any input on what I'm doing wrong? Thanks!

    CHAR2HEX PROC                   ; Accept a character, print it's ascii value in hex.

        MOV DX, OFFSET AskChar      ; Display prompt
        MOV AH, 09H
        INT 21H

        MOV AX, 0                   ; Clear AX

        MOV AH, 07H                 ; Get keyboard input w/ no echo (AL)
        INT 21H

        MOV BX, 16                  ; Set up the divisor (base 16)
        MOV CX, 0                   ; Initialize the counter
        MOV DX, 0                   ; Clear DX

        Divide:                         
                                    ; Dividend (what's being divided) in DX/AX pair, Quotient in AX, Remainder in DX.
            DIV BX                  ; Divide (will be word sized).
            PUSH AX                 ; Save DX (the remainder) to stack.

            ADD CX, 1               ; Add one to counter

            MOV DX, 0               ; Clear Remainder (DX)
            CMP AX, 0               ; Compare Quotient (AX) to zero
            JNE Divide              ; If AX not 0, go to "Divide:"

        Multiply:
                                    ; Multiply remainder (from stack) by 16 to get hex value.               
            MOV DX, 0               ; Clear DX           
            POP AX                  ; Get remainder from stack into AX.

            MUL BX                  ; Multiply AX * BX.  (DX= high order bits, AX = low order bits)
            MOV DX, AX

            SUB DL, 30h             ; ADD 30h to DL 
            MOV AH, 02h             ; 02h to display AH (DL)
            INT 21H                 ; Send to DOS

            LOOP Multiply           ; If more to do, Multiply again
                                    ; LOOP subtracts 1 from CX. If non-zero, loop.
            RET
    CHAR2HEX ENDP
END START

EDITED **

I finally got it! I was able to get the program to return the hex value of the ascii char that was pushed on the keyboard, but it only worked if each remainder was 0 through 9. It wouldn't display the A through F, and instead used colons, semicolons, etc...

I looked at an Ascii/Deicmal/Hex chart online, and noticed that the characters 0 through 9 are 30h through 39h. But character A (for hex 10) doesn't start until 40h. So I changed the program so that if the value was greater than 39h, it added 7h to DL and THEN display it.

    CHAR2HEX PROC                   ; Accept a character, print it's ascii value in hex.

        MOV DX, OFFSET AskChar      ; Display prompt
        MOV AH, 09H
        INT 21H

        MOV AH, 07H                 ; Get keyboard input w/ no echo (AL)
        INT 21H

        MOV CL, AL                  ; Copy user input (AL) to CL
        MOV AX, 0                   ; Clear AX (get rid of HO bits)
        MOV AL, CL                  ; Copy user input back into AL

        MOV BX, 16                  ; Set up the divisor (base 16)
        MOV CX, 0                   ; Initialize the counter
        MOV DX, 0                   ; Clear DX

        Div2:                         
                                    ; Dividend (what's being divided) in DX/AX pair, Quotient in AX, Remainder in DX.
            DIV BX                  ; Divide (will be word sized).
            PUSH DX                 ; Save DX (the remainder) to stack.

            ADD CX, 1               ; Add one to counter
            MOV DX, 0               ; Clear Remainder (DX)
            CMP AX, 0               ; Compare Quotient (AX) to zero
            JNE Div2              ; If AX not 0, go to "Div2:"

        getHex2:
            MOV DX, 0               ; Clear DX.
            POP DX                  ; Put top of stack into DX.
            ADD DL, 30h             ; Conv to character.

            CMP DL, 39h
            JG MoreHex2

        HexRet2:        

            MOV AH, 02h             ; 02h to display AH (DL)
            INT 21H                 ; Send to DOS

            LOOP getHex2            ; If more to do, getHex2 again
                                    ; LOOP subtracts 1 from CX. If non-zero, loop.
            JMP Skip2
        MoreHex2:
            ADD DL, 7h
            JMP HexRet2             ; Return to where it left off before adding 7h.
        Skip2:
            RET
    CHAR2HEX ENDP

解决方案

Your logic for base 10 conversion looks good: each remainder from dividing by 10 will give you a digit, and they will be ordered from the least significant digit to the most significant one, so you need to reverse the obtained digits before printing them. Pushing them to a stack and popping them when done will do the reversing in a nice and compact way.

For converting to hex, the operation is the same: divide by 16, get the remainder, reverse, and print. However, there are a few things to note: dividing by 16 is shifting right 4 bits. Remainder is value AND 0fH, so you don't actually need any arithmetic operations. Bit shifts and AND operation is sufficient. Moreover, you don't even need to involve the stack. You can do this from most significant nibble (four bits) to the least significant one, and print as you calculate them. The second thing that you seem to be struggling with is converting a nibble to a hex digit. Simply adding 30h is not enough. It is good enough for decimals, but for hex values, you've got the numbers 10 to 15 as well. These need to be added to 41h ('A' in ASCII) minus 10 instead. Alternatively, you can put the digits '0' to '9' and 'A' to 'F' in a table, and index them by the value of the nibble you want to print.

You may also want to write a routine that will read a number from input. Read each digit until you read a newline, convert character to decimal value, and update an accumulator that will keep the number you've read. You will need to use this for both hex and decimal output functions.

这篇关于8086大会(TASM):显示一个ASCII字符值作为十六进制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆