将字符串转换为整数的最小方法(反之亦然)

时间:2009-12-29 03:47:17

标签: c optimization assembly

我正在寻找一种将"123"之类的字符串转换为123这样的整数的极小方法,反之亦然。

我将在一个独立的环境中工作。这不是一个不成熟的优化。我正在创建必须符合512字节的代码,因此每个字节实际上都会计数。我将同时采用x86汇编(16位)和C代码(因为它很容易转换)

它不需要做任何健全性检查或任何事情......

我以为我看过一个递归实现的非常小的C实现,但我似乎找不到任何适合大小优化的东西..

那么有人能找到我(或创建)一个非常小的atoi / itoa实现吗? (它只需要与基数10一起工作)

编辑:(答案)(再次编辑,因为第一段代码实际上是错误的) 如果其他人遇到这个,这是我最终创建的代码。它可以适合21个字节!

;ds:bx is the input string. ax is the returned integer
_strtoint:
    xor ax,ax
    .loop1:
        imul ax, 10 ;ax serves as our temp var
        mov cl,[bx]
        mov ch,0
        add ax,cx
        sub ax,'0'
        inc bx
        cmp byte [bx],0
    jnz .loop1
ret

好的,上次编辑我发誓! 版本重量为42字节,负数支持..所以如果有人想使用这些,他们可以..


;ds:bx is the input string. ax is the returned integer
_strtoint:
    cmp byte [bx],'-'
    je .negate
    ;rewrite to negate DX(just throw it away)
    mov byte [.rewrite+1],0xDA
    jmp .continue
    .negate:
    mov byte [.rewrite+1],0xD8
    inc bx
    .continue
    xor ax,ax
    .loop1:
        imul ax, 10 ;ax serves as our temp var
        mov dl,[bx]
        mov dh,0
        add ax,dx
        sub ax,'0'
        inc bx
        cmp byte [bx],0
    jnz .loop1
    ;popa
    .rewrite:
    neg ax ;this instruction gets rewritten to conditionally negate ax or dx
ret

8 个答案:

答案 0 :(得分:3)

没有错误检查,'因为那个超过512B的wussies可以玩:

#include <ctype.h>
// alternative:
// #define isdigit(C) ((C) >= '0' && (C) <= '9')

unsigned long myatol(const char *s) {
  unsigned long n = 0;
  while (isdigit(*s)) n = 10 * n + *s++ - '0';
  return n;
}

gcc -O2将其编译为47个字节,但__ctype_b_loc的外部引用可能超出了您的承受能力......

答案 1 :(得分:1)

我的笔记本电脑上没有汇编程序来检查尺寸,但是随便看起来这应该更短:

; input: zero-terminated string in DS:SI
; result: AX
atoi proc
        xor cx, cx
        mov ax, '0'
    @@:
        imul cx, 10
        sub al, '0'
        add cx, ax
        lodsb
        jnz @b
        xchg ax, cx
        ret
atoi endp

答案 2 :(得分:0)

自己写。请注意,从数字中减去“0”可获得十次幂。所以,你循环数字,每次你把这个值乘以10,从当前字符中减去'0',然后加上它。 Codable在装配中很快就可以了。

答案 3 :(得分:0)

这是另一个没有任何检查。它假定一个空终止字符串。作为奖励,它会检查一个负号。使用Microsoft编译器(cl / O1)需要593个字节。

int myatoi( char* a )
{
   int res = 0;
   int neg = 0;

   if ( *a == '-' )
      {
      neg = 1;
      a++;
      }

   while ( *a )
      {
      res = res * 10 + ( *a - '0' );
      a++;
      }

   if ( neg )
      res *= -1;

   return res;
}

答案 4 :(得分:0)

的atoi(p)的 注册char * p; {     寄存器int n;     register int f;

n = 0;
f = 0;
for(;;p++) {
    switch(*p) {
    case ' ':
    case '\t':
        continue;
    case '-':
        f++;
    case '+':
        p++;
    }
    break;
}
while(*p >= '0' && *p <= '9')
    n = n*10 + *p++ - '0';
return(f? -n: n);

}

答案 5 :(得分:0)

如果使用-Os(优化空间)而不是-O2?

,是否有任何尺寸更小?

答案 6 :(得分:0)

您可以尝试将字符串打包成BCD(0x1234),然后使用x87 fbld和第二条指令来获得20世纪80年代的解决方案,但我不确定它会更小,因为我不记得有任何打包指令。< / p>

答案 7 :(得分:0)

你是如何让世界上的可执行文件如此之小?!此代码在使用gcc -Os -m32 -c -o atoi.o atoi.c编译时生成316字节.o文件,在编译和链接(添加空int main(){})时使用gcc -Os -m32 -o atoi atoi.c生成8488字节可执行文件。这是在Mac OS X Snow Leopard上......

int myatoi(char *s)
{
 short retval=0;
 for(;*s!=0;s++) retval=retval*10+(*s-'0');
 return retval;
}