2012-04-23 55 views
1

**爲澄清和「更清晰」的代碼進行了編輯。8086裝配(TASM):將ASCII字符值顯示爲HEX

我試圖從鍵盤(任何字符)接受一個字符,並將它的ASCII值轉換爲十六進制,然後顯示它。

我知道如何從基地10轉換爲十六進制,但只是爲了確保我沒有使用不正確的術語:

如果我在爲我的ASCII值輸入「C」,它的十進制值是63。 63除以16(十六進制是16進制)= 3.9375。稍後保存3的商數。剩餘*基數(.9375 * 16)= 15. 15是十六進制字符「F」。

商數除以基數(3/16)= 0.1875。商數爲零,所以這是轉換的最後一步。剩餘*基數(.1875 * 16)= 3

從最後到第一個讀取它們(如果考慮堆棧,請先讀取「先進先出」),然後將「3F」數字「63」(這是ASCII爲「c」)

這是正確的,是嗎?

這是很簡單的閱讀,我希望。我只是從鍵盤(AL)獲取字符,將BX設置爲除數(基數爲16),然後將AL除以BX,將餘數存儲在堆棧中,然後在堆棧中循環並嘗試顯示它。

我覺得我的問題是我的乘法和INT 21H/02H有問題。我不確定是否需要添加30h才能顯示該字符或不...

最重要的是,我甚至不確定是否需要在該點(顯示)仍然無論如何,因爲我還沒有想出如何將10-15轉換爲十六進制的AF。

我試着和我的老師說話,等了30分鐘後,他完成了和我班上另一羣學生的談話(關於他班的另一個班級的事情,而不是這個......這讓我非常厭煩一點),我得到的最多是「重新開始」。

當問到「使用SHR和SHL怎麼辦?」正如它向我指出的那樣,但我被告知可以不這樣做,並且我不能使用這些命令(它們在課堂上沒有被覆蓋)。

我在做什麼錯誤的任何輸入?謝謝!

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 **

我終於得到它!我能夠讓程序返回鍵盤上按下的ascii字符的十六進制值,但只有當每個餘數是0到9時才起作用。它不會顯示A到F,而是使用冒號,分號等...

我在網上查看了一個Ascii/Deicmal/Hex圖表,並注意到字符0到9是從30h到39h。但字符A(十六進制爲10)直到40h纔開始。所以我改變了程序,所以如果這個值大於39h,它會在DL上加7h,然後顯示它。

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 
+0

我可以讓我的程序從ASCII轉換爲十六進制,但只有當每個值爲9或更小。 因此,例如,使用「a」作爲輸入會導致在屏幕上打印「61」。 「b」導致「62」。但如果我輸入「K」,結果爲「4;」,並且實際上並沒有將最後一位數字轉換爲「A-F」... 這就是我目前無法弄清楚的。這東西很難! – SalarianEngineer 2012-04-25 22:27:20

+0

你想要編寫'if(a <= 9)a + = 0x30 else a + = 0x41'(假設a總是在0到15之間)來獲得這些數字。這不是很難,但很乏味。 :) – vhallac 2012-04-26 10:01:13

回答

1

您的基地10轉換邏輯看起來不錯:每個從除以10,會給你一個數字餘,他們會從最低顯著數字最顯著一個排序,所以你需要扭轉在打印之前獲得數字。將它們推入堆棧並在完成時彈出它們,將以非常緊湊的方式進行反轉。

對於轉換爲十六進制,操作是相同的:除以16,得到餘數,反轉和打印。但是,有幾點需要注意:除以16將右移4位。其餘的是value AND 0fH,所以你實際上並不需要任何算術運算。位移和AND操作就足夠了。而且,你甚至不需要涉及堆棧。您可以從最重要的半字節(四位)到最不重要的一個,並在計算它們時進行打印。你似乎正在努力的第二件事是將一個半字節轉換爲十六進制數字。僅僅添加30h是不夠的。對於小數點來說已經足夠了,但對於十六進制值,您也可以得到10到15的數字。這些需要被添加到41h(ASCII中的'A')減10。或者,您可以在表格中將數字「0」設置爲「9」和「A」設置爲「F」,並將它們索引爲要打印的半字節值。

您可能還想寫一個例程,從輸入中讀取一個數字。讀取每個數字,直到您讀取換行符,將字符轉換爲十進制值,並更新一個累加器,以保留您讀取的數字。你將需要使用它來同時使用十六進制和十進制輸出函數。

+0

Vhallac,我很抱歉,如果這是多餘的,但我在原帖中發佈了新的代碼(帶有編輯)......我不確定它是否通知您這個或沒有,但如果您有你能看一下嗎? – SalarianEngineer 2012-04-25 20:38:26

+0

特別困難的是,當你寫到「value AND 0fh」時......我對這個時間根本不熟悉。 – SalarianEngineer 2012-04-25 20:53:17

+0

你似乎試圖把整個程序放在一起,而沒有確定每件作品都很好。如果我是你,我會從每個子程序開始,首先打印十進制或十六進制值,然後用常量數據(不是從鍵盤讀取)進行測試。一旦你有了這些構建模塊,你就可以從鍵盤上添加閱讀,等等。下面的dwelch的答案是非常明智的:你首先使用你熟悉的語言對算法進行分類。 – vhallac 2012-04-26 09:52:22

1

先用C或其他語言編寫程序。不要使用語言庫,例如,不要使用printf(「%x \ n」,數字)來顯示十六進制,但可以按照您的建議將該數字重複除以10,並將它們保存在某處。現在請記住,除以十之後的餘數(模)是0-9之間的某個值,以便在ascii中顯示此處,您需要像上面提到的那樣添加0x30。 123變爲12剩餘3,然後12變爲1剩餘2,並且1變爲0剩餘1,1 + 0x30 = 0x31顯示2 + 0x30變爲0x32顯示,3 + 0x30變爲0x33顯示。

十六進制沒有什麼不同,基數是16而不是10.由於vhallac提到,雖然你可以掩碼和移位,而不是使用除法運算符。使用基本操作(add,sub,divide,shift等)的低級別,然後用匯編語言重新編寫該代碼。

最終,您可能會達到不需要用其他語言證明您的程序並以asm開頭的地步。

+0

嗯...不太清楚如何在回覆中發佈代碼,所以我只是在我自己的帖子上發表評論,我猜?底線: 我在C#中編寫了一個控制檯應用程序,要求輸入一個數字。然後我把這個數字除以10,將餘數和商數保存在不同的變量中,將餘數輸出到列表(我的「堆棧」)。畢竟完成後,我有一個循環遍歷列表,併爲每個值添加30,附加一個「h」,並打印出來。我不確定這是否是一個「捷徑」(添加「h」),因爲我不確定如何在C#中使用Hex做任何事情。 – SalarianEngineer 2012-04-23 22:12:49