我正在编写一堆宏来处理MASM中的大数字,我发现自己需要从一系列数字转换为数字。基本上,为了克服MASM大小的限制,我一直把bignums作为字符串传递。因此,bignum调用看起来像:
MOV_BIG_NUM [eax], <1234567891011121314151617181920212223>
我有一个实现可以处理(据我所知)在2的幂的基础中传递的字符串。也就是说,调用如:
MOV_BIG_NUM [eax], <1001101111010101101011110101000011101b> ;Base 2
MOV_BIG_NUM [eax], <0123456710121314151617202122232425262o> ;Base 8
MOV_BIG_NUM [eax], <123456789ABCDEF101112131415161718191Ah> ;Base 16
将处理好。然而,我用于那些方法的方法并不能很好地(或者实际上)很好地转换为不是2的幂的基数。当然,最重要的是十进制,但我很想得到一个使用任意基函数的方法。我一直用于2的幂的方法是按顺序访问字节,必要时移位数字,并用现有数字按位or
。所以我的十六进制数字方法看起来像这样(这是一个高度简化的版本):
;foreach digit in list of digits
;eax contains the start of memory for the bignum
IF bit_offset EQ 0 ;Only move a new value in when the offset has just changed
mov ebx, dword ptr [eax + byte_offset] ;Get the current value at the dword's offset
ENDIF
digit = digit SHL bit_offset ;Shift the digit by a certain offset, so that we can store multiple digits in one byte
or ebx, digit
bit_offset = bit_offset + 4
IF bit_offset EQ ( 32 ) ;Number of bits in a dword
mov dword ptr [eax + byte_offset], ebx ;Move the dword back
byte_offset = byte_offset + 4 ;Number of bytes in a dword
bit_offset = 0;
ENDIF
;end foreach
然而,这种方法显然不适用于任意基础。我如何将十进制数字的连续列表转换为十六进制数?
答案 0 :(得分:1)
您可以执行算术乘法10并添加带有十六进制字符串的数字。从那里你可以组成十进制到十六进制的字符串转换。
C中的插图:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef unsigned uint;
int chhex2val(char ch)
{
if (ch >= '0' && ch <= '9')
return ch - '0';
if (ch >= 'A' && ch <= 'F')
return ch - 'A' + 10;
if (ch >= 'a' && ch <= 'f')
return ch - 'a' + 10;
abort();
return 0;
}
char val2chhex(int v)
{
if (v >= 0 && v < 16)
return "0123456789ABCDEF"[v];
abort();
return '0';
}
// Multiplies a hex string like "17F" by 10 and
// returns a string with the product (e.g. "0EF6").
// The original string isn't modified.
char* mulh10(char* h)
{
size_t l = strlen(h);
char* p = malloc(l + 1 + 1);
size_t i;
uint c = 0;
if (p == NULL)
abort();
p[l + 1] = '\0';
for (i = 0; i < l; i++)
{
c += chhex2val(h[l - 1 - i]) * 10;
p[l - i] = val2chhex(c % 16);
c /= 16;
}
p[0] = val2chhex(c);
return p;
}
// Adds (arithmetically) to a hex string like "17F" a hex/dec digit, e.g. '9'.
// Returns the modified original string (e.g. "188").
char* addhd(char* h, char d)
{
size_t l = strlen(h);
size_t i;
uint c = chhex2val(d);
for (i = 0; c && i < l; i++)
{
c += chhex2val(h[l - 1 - i]);
h[l - 1 - i] = val2chhex(c % 16);
c /= 16;
}
return h;
}
int main(void)
{
char num[] = "17F";
printf("\"17F\" (hex) * 10 = \"%s\" (hex)\n", mulh10(num));
printf("\"17F\" (hex) + '9' = \"%s\" (hex)\n", addhd(num, '9'));
printf("\"65535\" (dec) = \"%s\" (hex)\n",
addhd(mulh10(addhd(mulh10(addhd(mulh10(addhd(mulh10(addhd(mulh10(
"0"), '6')), '5')), '5')), '3')), '5'));
return 0;
}
输出(ideone):
"17F" (hex) * 10 = "0EF6" (hex)
"17F" (hex) + '9' = "188" (hex)
"65535" (dec) = "00FFFF" (hex)