[英]In assembly why can't a hexadecimal number be printed without shifting?
此代碼取自在線示例。 假設我有要在DL中打印的變量。
DISPLAY_HEX PROC NEAR
MOV BL,DL
MOV BH,0
MOV CL,4
SHL BX,CL
MOV DL,BH
CALL ONE_DIGIT
MOV CL,4
SHR BL,CL
MOV DL,BL
CALL ONE_DIGIT
RET
DISPLAY_HEX ENDP
ONE_DIGIT PROC NEAR
CMP DL,9
JA LETTER
ADD DL,48
JMP NEXT
LETTER: ADD DL, 'A'-10
NEXT: MOV AH,02H
INT 21H
END: RET
ONE_DIGIT ENDP
為什么要換班? 不能像小數一樣打印嗎? 另外,為什么在這里同時使用SHR和SHL ?
在base16(十六進制)中,您有16個可能的數字( 0..F
),因此恰好需要4位來表示一個十六進制數字(log2(16)== 4)。 在這里,我說的是數字的含義( 0..F
或base10中的0..15
),而不是ASCII字符。
因此,一個字節可以容納兩個十六進制數字。 假設DL
擁有以下位: XXXXYYYY
(其中每個X
和Y
都是二進制0或1)。
首先,將16位寄存器BX
向左移4位。 BX
由BL
(最低有效字節)和BH
(最高有效字節)組成。 BH
已設置為0,並且BL
包含輸入,因此在移位之前BX
包含位00000000XXXXYYYY
。 移位后將包含0000XXXXYYYY0000
。
然后, BX
的最高有效字節(即BH
,現在包含0000XXXX
)被移至DL
,轉換為字符並打印。
對於第二部分,現在包含YYYY0000
BL
YYYY0000
右移4位,得到0000YYYY
。 然后將該值轉換為字符並打印。
您的代碼非常復雜,難怪它會令人困惑。 它通過左移BX獲得DL的高半字節,因此將兩個半字節分為BH和BL,但BL中的半字節在前4個字節中。
您需要進行一次移位才能將高4位降低到寄存器的底部。
在實數8086上,使用AND來僅保留低4位會更容易,並且速度要快得多(在這種情況下,每個移位的計數需要一個時鍾周期,這與帶有桶形移位器ALU的現代CPU可以在1個時鍾周期內進行任意移位的現代CPU不同) 。
這是一個更簡單易懂的實現,它也更緊湊,因此在實際的8086上更快更好。
; Input in DL
; clobbers AX, CL, DX
DISPLAY_HEX PROC NEAR
mov dh, dl ; save a copy for later
mov cl, 4
shr dl, cl ; extract the high nibble into an 8-bit integer
CALL ONE_DIGIT
and dh, 0Fh ; clear the high nibble, keeping only the low nibble
mov dl, dh ; and pass it to our function
CALL ONE_DIGIT
RET
DISPLAY_HEX ENDP
為了節省代碼大小, mov dl, 0Fh
/ and dl, dh
每條指令僅2個字節,而不是for and dh, 0Fh
的3個字節,它使mov
脫離了亂序執行的關鍵路徑。
ONE_DIGIT
的實現還具有不必要的復雜分支。 (通常,您可以使用查找表實現半字節-> ASCII,但它只需要一個分支,而不是兩個分支。運行額外的add
要比額外的jmp
便宜。)
; input: DL = 0..15 integer
; output: AL = ASCII hex char written
; clobbers = AH
ONE_DIGIT PROC NEAR
CMP DL,9
JBE DIGIT
ADD DL, 'A'-10 - '0'
DIGIT:
ADD DL, '0'
MOV AH,02H
INT 21H ; write char to stdout, return in AL. Checks for ^c/break
RET
ONE_DIGIT ENDP
我們可以將ADD dx, '00'
(並更改cmp
)同時對兩個半字節進行操作(在DH和DL中將它們分別隔離之后)。
我們也可以提升MOV AH,02H
,因為int 21h
/ ah=2
不會修改AH。 。
如果我們關心性能,我們將創建一個2個字符的字符串,並使用一個int 21h
系統調用一次打印兩個數字。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.