2016-11-23 63 views
0

我如何轉換一個4位十六進制數爲2的補負我如何轉換一個4位十六進制數爲2的補負

我想輸入一個4位十六進制數字,如果是負數,它會被轉換爲正值,然後我想用兩種補充技術來找到結果。

例如,如果我輸入F520h,輸出將是-F520h = 0AE0h

的問題是,當我輸入的4位數字,它是ASCII,我怎樣才能確定它是否是一個數字或一個數字,沒有檢查0-9,AF ..

+0

*「如何確定它是否是數字或數字,而不檢查0-9,AF ..」 *你能詳細解釋一下嗎?這聽起來像是自相矛盾。如果您有4個ASCII字符作爲輸入,並且您想知道它們是否構成有效的十六進制數字,則必須檢查每個字符是否來自[0-9A-F]集。看不到任何其他方式。當然,你可以將任意4個字節的數值轉換爲只對有效輸入產生有意義結果的方式(垃圾進入=>垃圾進出),所以如果你不介意錯誤的輸出,就不需要檢查。 – Ped7g

+0

@ Ped7g它沒有任何意義。如果我得到F520h的輸入,我怎樣才能得到結果0AE0h? –

+0

對不起,但對我來說這是「顯而易見的」(怎麼做),所以我不確定哪一部分令你困惑。我試圖在答案中把它分解成簡單的主題,也許你會有能力更好地指出給你帶來麻煩的特定步驟。 – Ped7g

回答

1

事情你應該明白做好準備,爲這個設計代碼:

如何輸入「串」被存儲在內存中("F520h"至少5個字節,也許更多,與一些終結者值附加後) - 取決於你如何閱讀來自用戶的輸入,諮詢使用的API文檔。

什麼是ASCII表格,即如何將單個字符[0-9A-Fa-f]轉換爲值0 - 15。提示:如果仔細檢查'a''A'的編碼,您可能會發現如何將它們轉換爲值10,其中一個sub(或add)和and(也適用於其他字母)。將字符'0'轉換爲值0甚至更​​容易。

如何從四個0-15(4位)值中構建16位值。提示:4 * 4位= 16位,所以這隻能通過位操作來實現,而不涉及任何乘法/除法運算。

如何測試,如果值是負的(可能是CPU已經有「SF」標誌您16b的價值構建最後一條指令後置,因此,所有你需要的是js instruction然後。

如何否定16B價值... 86有neg instruction

如何輸出得到的數字:

會要求你打破16位值分爲四個4B值(再次按位運算,應該夠了,像andshr指令做最的工作)

把這些0 - 15 4位值值回ASCII字符(如此反覆理解ASCII編碼應該幫助)。

爲您的輸出API調用(可能需要一些末尾的終止符值或準確的輸出字符串長度)從所需格式的字符創建輸出字符串。


如果你不知道什麼大會,這可能是非常複雜的,以指令的形式寫正確,並會採取幾天可能。

雖然在算法方面它非常簡單(複雜性隱藏在要完成的工作量上),但我希望你能「看到」我列出的每個點背後的數學。這些步驟的排列順序與我腦海中的算法有些相關。

確保您必須首先知道如何計算從理論層面上的(算法)的輸入輸出中,描述了在只涉及基本的數值運算(檢查的8086個CPU ASM指令概述獲得的想法非常簡單的步驟是什麼這種操作對於CPU來說是「基本」的,並且它可以如何操作數字/位)。

然後你可以專注於如何用幾個x86指令來實現每一步。

關於堆棧溢出問題,您也會遇到很多關於如何打印十六進制值等特定步驟的問題,例如如何打印十六進制值等,以便您可以檢查這些想法(只要確保答案的目標平臺與您的相同,或者理解答案背後的想法,所以你可以自己寫)。


編輯:順便說一句,這個任務有另一種主要方式如何解決它,你只需要否定的ASCII編碼的十六進制數,你甚至都不需要將其轉換爲數值,它可能修補ASCII字符本身以產生neg結果。雖然neg是有點棘手(但可行)。我記得this for xor(在C++中,但是這幾乎是1:1編譯爲ASM指令),當需要高性能時,轉換爲數字並返回字符串代價太高。

但是,如果您正在嘗試學習彙編,最好先以第一種方式來完成,以便您可以瞭解並理解所有這些轉換以及十六進制數字如何在彙編中的字符串< - >之間進行轉換。

0

接着代碼做這項工作:用戶輸入一個十六進制數(最多4位數字,例如,「F520」)作爲字符串,轉換在ax的字符串號碼,neg施加到ax,結果被轉換回爲十六進制字符串和顯示(例如「0AE0」),你只需複製粘貼並運行它:

.model small 
.stack 100h 
.data 

msg1 db 10,13,10,13,'ENTER 1 TO 4 HEX DIGITS:$' 
msg2 db 10,13,'NEG IS:$' 
msg3 db 10,13,10,13,'DO YOU WANT TO DO IT AGAIN (Y/N)?$' 
msg4 db 10,13,'ILLEGAL CHARACTER- ENTER 0-9 OR A-F:$' 

hex db 5,?,5 dup(?) ;VARIABLE WITH 3 SECTIONS. 
buffer db '0000$' 

.code 
    mov ax, @data 
    mov ds, ax 

again: 

;CLEAR BUFFER (IN CASE IT HOLDS PREVIOUS RESULT). 
    call clear_buffer 

;DISPLAY 'ENTER 1 TO 4 HEX DIGITS:$' 
    mov ah, 9 
    lea dx, msg1 
    int 21h 

;CAPTURE HEX NUMBER AS STRING. 
    mov ah, 0ah 
    lea dx, hex 
    int 21h 

;CONVERT HEX-STRING TO NUMBER. 
    lea si, hex+2  ;CHARS OF THE HEX-STRING. 
    mov bh, [si-1]  ;SECOND BYTE IS LENGTH. 
    call hex2number  ;NUMBER RETURNS IN AX. 

    neg ax 

;CONVERT NUMBER BACK TO HEX-STRING TO DISPLAY. 
    lea si, buffer 
    call number2hex  ;STRING RETURNS IN SI (BUFFER). 

;DISPLAY 'NEG IS :$' 
    mov ah, 9 
    lea dx, msg2 
    int 21h    

;DISPLAY NUMBER AS STRING. 
    mov ah, 9 
    lea dx, buffer 
    int 21h 

illegal: ;JUMP HERE WHEN INVALID CHARACTER FOUND. 

;DISPLAY 'DO YOU WANT TO DO IT AGAIN (Y/N)?$' 
    mov ah, 9 
    lea dx, msg3 
    int 21h 

;CAPTURE KEY. 
    mov ah, 1 
    int 21h 
    cmp al,'y' 
    je again 
    cmp al,'Y' 
    je again 

;TERMINATE PROGRAM. 
    mov ax, 4c00h 
    int 21h 

;--------------------------------------------- 
;FILL VARIABLE "BUFFER" WITH "0". 
;EVERYTIME THE USER WANTS TO DO IT AGAIN, THE 
;PREVIOUS RESULT MUST BE CLEARED. 

clear_buffer proc 
    lea si, buffer 
    mov al, '0' 
    mov cx, 4 
clearing: 
    mov [si], al 
    inc si 
    loop clearing 

    ret 
clear_buffer endp 

;--------------------------------------------- 
;INPUT : BH = STRING LENGTH (1..4). 
;   SI = OFFSET HEX-STRING. 
;OUTPUT : AX = NUMBER. 

hex2number proc 
     MOV AX, 0  ;THE NUMBER. 
    Ciclo: 
;--------------------------------------------- 
;  SHL AX, 4  ;SHIFT LEFT LOWER 4 BITS. 
;SHIFT LEFT AL AND AH MANUALLY 4 TIMES TO SIMULATE SHL AX,4. 
     shl al, 1 
     rcl ah, 1 
     shl al, 1 
     rcl ah, 1 
     shl al, 1 
     rcl ah, 1 
     shl al, 1 
     rcl ah, 1 
;--------------------------------------------- 

     MOV BL, [ SI ] ;GET ONE HEX CHAR FROM STRING. 

     call validate 

     CMP BL, 'A'  ;BL = 'A'..'F' : LETTER. 
     JAE letterAF ;BL = '0'..'9' : DIGIT. 
    ;CharIsDigit09. 
     SUB BL, 48  ;CONVERT DIGIT TO NUMBER. 
     JMP continue 
    letterAF:    
     SUB BL, 55  ;CONVERT LETTER TO NUMBER. 
    continue: 
     OR AL, BL  ;CLEAR UPPER 4 BITS. 
     INC SI   ;NEXT HEX CHAR. 
     DEC BH   ;BH == 0 : FINISH. 
     JNZ Ciclo  ;BH != 0 : REPEAT. 
    Fin: 
     RET 
hex2number endp 

;--------------------------------------------- 
;INPUT : BL = HEX CHAR TO VALIDATE. 

validate proc 
    cmp bl, '0' 
    jb error  ;IF BL < '0' 
    cmp bl, 'F' 
    ja error  ;IF BL > 'F' 
    cmp bl, '9' 
    jbe ok  ;IF BL <= '9' 
    cmp bl, 'A' 
    jae ok  ;IF BL >= 'A' 
error:  
    pop ax  ;REMOVE CALL VALIDATE. 
    pop ax  ;REMOVE CALL HEX2NUMBER. 
;DISPLAY 'ILLEGAL CHARACTER- ENTER 0-9 OR A-F$' 
    mov ah, 9 
    lea dx, msg4 
    int 21h 
    jmp illegal ;GO TO 'DO YOU WANT TO DO IT AGAIN (Y/N)?$' 
ok:  
    ret 
validate endp 

;--------------------------------------------- 
;INPUT : AX = NUMBER TO CONVERT TO DECIMAL. 
;  SI = OFFSET STRING TO STORE THE HEX CHARS. 
;ALGORITHM : EXTRACT LOWEST 4 BITS OF AX, CON- 
;VERT THEM IN HEX DIGIT, SHIFT RIGHT AX 4 BITS, 
;REPEAT THE PROCESS 3 MORE TIMES (BECAUSE AX 
;CONTAINS 4 GROUPS OF 4 BITS, EACH GROUP IS ONE 
;HEX CHAR. 

number2hex proc 
    add si, 3 
n2h:  
;GET 4 BITS FROM AX. 
    mov bl, al  ;GET LOWEST 4 BITS OF AX. 
    and bl, 00001111b ;ISOLATE LOWER 4 BITS. 
    shr ax, 4   ;GET RID OF THOSE 4 BITS. 
;CONVERT 4 BITS TO HEX CHAR. 
    cmp bl, 9 
    ja letter         
    add bl, 48  ;CONVERT TO DIGIT 0..9. 
    jmp skip_letter 
letter: 
    add bl, 55  ;CONVERT TO LETTER A..F. 
skip_letter: 
    mov [si], bl 
    dec si 
    cmp ax, 0 
    jne n2h 

    ret 
number2hex endp 

;------------------------------------------ 

end 
相關問題