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 |
使用的基数使用常量 BASE2 ,BASE4 ,BASE8 和 BASE16 表示 |
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 位。
添加基数:
- 定义一个新的常量
BASEx
,其中 x 是 2 n 。
名为 D 的低位字节是 D = n 。
名为 S 的高位字节是较高组的位(以位为单位)。它可以计算为S = ñ ·(⌈16/ N ⌉ - 1)。 - 将必要的数字添加到字符串
DIGITS
。
示例:添加基数 32
我们有 D = 5 和 S = 15,所以我们定义 BASE32 EQU 0f05h
。
然后我们再添加十六个数字:DIGITS db "0123456789abcdefghijklmnopqrstuv"
。
应该清楚,可以通过编辑 DIGITS
字符串来更改数字。
1 如果 B 是基数,则每个定义有 B 个数字。因此,每位数的位数是 log 2 ( B )。对于两个碱基的功率,这简化为 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 2 ( log 2 ( B ))必须是整数。