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 ))必须是整数。