【问题标题】:Convert a Series of Decimal Digits into a Hexadecimal Big Number in MASM在 MASM 中将一系列十进制数字转换为十六进制大数
【发布时间】:2012-10-13 03:53:29
【问题描述】:

我正在编写一堆宏来处理 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

但是,这种方法显然不适用于任意基数。我将如何将十进制数字的顺序列表转换为十六进制数字?

【问题讨论】:

    标签: assembly x86 masm bignum


    【解决方案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)
    

    【讨论】:

    • 我知道你打算用这个去哪里。我将尝试在汇编中实现一个实现
    猜你喜欢
    • 1970-01-01
    • 2015-06-25
    • 2015-01-26
    • 1970-01-01
    • 2013-05-31
    • 2018-07-04
    • 1970-01-01
    • 2014-04-16
    相关资源
    最近更新 更多