MS-DOS TASMMASM 函式以二進位制四進位制八進位制十六進位制列印 16 位數

以二進位制,四進位制,八進位制,十六進位制和一般二次冪列印數​​字

所有基數為 2 的冪,如二進位制(2 1 ),四進位制(2 2 ),八進位制(2 3 ),十六進位制(2 4 )基,每個數字 1 具有整數位。
因此,為了檢索數字的每個數字 2 ,我們簡單地從 LSb(右)開始打破 n 位元的數字介紹組。
例如,對於四元基,我們以兩位組的形式打破一個 16 位數。有 8 個這樣的團體。
並非所有兩個基數的冪都具有適合 16 位的整陣列; 例如,八進位制基數有 5 組 3 位元,佔 16 箇中的 3·5 = 15 位元,留下 1 位元 3 的部分組

演算法很簡單,我們用一個移位後跟一個 AND 運算來隔離每個組。
此過程適用於組的每個大小,換句話說,適用於任何 2 的基本功率。

為了以正確的順序顯示數字,函式通過隔離最重要的組(最左邊的)開始,因此重要的是要知道:a) 一組是多少位 D 和 b) 最左邊的位位置 S 小組開始。
這些值經過預先計算並儲存在精心設計的常量中。

引數

必須將引數推入堆疊。
每個都是 16 位寬。
它們按推動順序顯示。

引數 描述
N 要轉換的數字
Base 使用的基數使用常量 BASE2BASE4BASE8BASE16 表示
Print leading zeros 如果*為零,*則不列印非重要零,否則為。但是數字 0 列印為 0

用法

push 241
push BASE16
push 0
call print_pow2              ;Prints f1

push 241
push BASE16
push 1
call print_pow2              ;Prints 00f1

push 241
push BASE2
push 0
call print_pow2              ;Prints 11110001

TASM 使用者注意事項 :如果在使用 EQU 的程式碼之後放置使用 EQU 定義的常量,請使用 TASM/m 標誌啟用多次傳遞,否則你將獲得 Forward reference needs override 。 ** **

;Parameters (in order of push):
;
;number
;base (Use constants below)
;print leading zeros
print_pow2:
 push bp
 mov bp, sp

 push ax
 push bx
 push cx
 push dx
 push si
 push di

 ;Get parameters into the registers

 ;SI = Number (left) to convert
 ;CH = Amount of bits to shift for each digit (D)
 ;CL = Amount od bits to shift the number (S)
 ;BX = Bit mask for a digit

 mov si, WORD PTR [bp+08h]
 mov cx, WORD PTR [bp+06h]            ;CL = D, CH = S

 ;Computes BX = (1 << D)-1
 
 mov bx, 1
 shl bx, cl
 dec bx

 xchg cl, ch              ;CL = S, CH = D

_pp2_convert:
 mov di, si
 shr di, cl
 and di, bx         ;DI = Current digit

 or WORD PTR [bp+04h], di             ;If digit is non zero, [bp+04h] will become non zero
                      ;If [bp+04h] was non zero, result is non zero
 jnz _pp2_print                       ;Simply put, if the result is non zero, we must print the digit

 
 ;Here we have a non significant zero
 ;We should skip it BUT only if it is not the last digit (0 should be printed as "0" not
 ;an empty string)

 test cl, cl
 jnz _pp_continue

_pp2_print:
 ;Convert digit to digital and print it

 
 mov dl, BYTE PTR [DIGITS + di]
 mov ah, 02h
 int 21h

_pp_continue:
 ;Remove digit from the number

 sub cl, ch
jnc _pp2_convert

 pop di
 pop si
 pop dx
 pop cx
 pop bx
 pop ax

 pop bp
 ret 06h

資料

This data must be put in the data segment, the one reached by `DS`.

DIGITS    db    "0123456789abcdef"

;Format for each WORD is S D where S and D are bytes (S the higher one)
;D = Bits per digit  --> log2(BASE)
;S = Initial shift count --> D*[ceil(16/D)-1]

BASE2    EQU    0f01h
BASE4    EQU    0e02h
BASE8    EQU    0f03h
BASE16    EQU    0c04h

NASM 移植

要將程式碼移植到 NASM,請從記憶體訪問中刪除 PTR 關鍵字(例如,mov si, WORD PTR [bp+08h] 變為 mov si, WORD PTR [bp+08h]

擴充套件功能

該功能可以很容易地擴充套件到最高 2 255 的 任何基礎,但是高於 2 16 的 每個基數將列印相同的數字,因為該數字僅為 16 位。

新增基數:

  1. 定義一個新的常量 BASEx,其中 x 是 2 n
    名為 D 的低位位元組是 D = n
    名為 S 的高位位元組是較高組的位(以位為單位)。它可以計算為S = ñ ·(⌈16/ N ⌉ - 1)。
  2. 將必要的數字新增到字串 DIGITS

示例:新增基數 32

我們有 D = 5 和 S = 15,所以我們定義 BASE32 EQU 0f05h
然後我們再新增十六個數字:DIGITS db "0123456789abcdefghijklmnopqrstuv"

應該清楚,可以通過編輯 DIGITS 字串來更改數字。

1 如果 B 是基數,則每個定義有 B 個數字。因此,每位數的位數是 log 2B )。對於兩個鹼基的功率,這簡化為 log 2 (2 n )= n ,其根據定義是整數。

2 在這種情況下,隱含地假設所考慮的基數是 2 基數 2 n 的冪。

3 對於基數 B = 2 n 具有整數個位組,它必須是 n | 16( n 除以 16)。由於 16 中唯一的因子是 2,因此 n 必須是 2 的冪。所以 B 的形式為 2 2 k 或等效 log 2log 2B ))必須是整數。