C 将字符串转换为整数的最小方法(反之亦然)
我正在寻找一种非常小的方法,将像C 将字符串转换为整数的最小方法(反之亦然),c,optimization,assembly,C,Optimization,Assembly,我正在寻找一种非常小的方法,将像“123”这样的字符串转换成像123这样的整数,反之亦然 我将在一个独立的环境中工作。这不是一个过早的优化。我正在创建必须适合512字节的代码,所以每个字节实际上都有计数。我将同时使用x86汇编(16位)和C代码(因为这很容易转换) 它不需要做任何健康检查或任何事情 我以为我看到过一个非常小的C实现是递归实现的,但我似乎找不到任何用于大小优化的东西 那么,有人能找到我(或创建)一个非常小的atoi/itoa实现吗?(但它只需要使用基数10) 编辑:(答案)(再次编
“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
你自己写吧。请注意,从一个数字中减去“0”得到十的幂。所以,你把这些数字循环下来,每次你把这个值乘以10,从当前字符中减去“0”,然后加上它。可在无时间限制的情况下在汇编中进行编码。无错误检查,因为这是针对拥有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;
}
#包括
//备选方案:
//#define isdigit(C)((C)>='0'&&&(C),这里是另一个未经任何检查的字符串。它假设以null结尾的字符串。作为奖励,它检查负号。使用Microsoft编译器(cl/O1)需要593字节
原子能机构(p)
寄存器char*p;
{
寄存器int n;
寄存器INTF
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);
n=0;
f=0;
对于(;;p++){
开关(*p){
案例“”:
案例'\t':
继续;
案例'-':
f++;
格“+”:
p++;
}
打破
}
如果使用-Os(优化空间)而不是-O2,那么(*p>='0'&&&&*p是否有任何尺寸更小?您可以尝试将字符串打包到BCD(0x1234)中然后在80年代的解决方案中使用x87 fbld和fist指令,但我不确定它是否会更小,因为我不记得有任何打包指令。你们这些人到底是怎么把可执行文件弄得这么小的?!这段代码在使用gcc-Os-m32-c-o atoi.o atoi.c
a编译时会生成一个316字节的.o文件编译并链接(添加了一个空的int main(){}
与gcc-Os-m32-o atoi atoi.c
)时,将生成一个8488字节的可执行文件
int myatoi(char *s)
{
short retval=0;
for(;*s!=0;s++) retval=retval*10+(*s-'0');
return retval;
}
我的笔记本电脑上没有装配工来检查尺寸,但随便说一下,看起来应该更短一些:
; 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
您要转换的数字的大小是否有任何限制?32位还是64位?有符号还是无符号?处理有符号的数字是一种奖励,但我只选择16位数字嗯,哦,有人正在编写引导程序:)这是一个竞赛。一个引导扇区可以容纳多少内容。我正在寻找一个半生不熟的Forth解释程序,我还以为它是为了4k或256b演示:如果没有错误检查,为什么要检查每个字符都是一个数字?只需循环,直到你看到一个\0。我认为你不需要将C源代码放入512字节。噢..整洁忘记了lods
指令..我必须在下班后检查这个问题…调试符号或ELF头是很常见的事情…您只需尝试使用交叉编译器在独立环境中创建平面二进制文件…或者只需将其反汇编并计算字节数。。。
; 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