Assembly 检查程序集中输入字符的最干净方法是0到9之间
问题是在RISC-V中将字符串转换为int 如果存在任何非0~9的字符,请立即返回-1 但我想知道是否有任何方法可以通过使用最小指令来检查它 我的方法是将48和57(对应于ASCII中的0~9)放入临时寄存器,Assembly 检查程序集中输入字符的最干净方法是0到9之间,assembly,digits,micro-optimization,riscv,atoi,Assembly,Digits,Micro Optimization,Riscv,Atoi,问题是在RISC-V中将字符串转换为int 如果存在任何非0~9的字符,请立即返回-1 但我想知道是否有任何方法可以通过使用最小指令来检查它 我的方法是将48和57(对应于ASCII中的0~9)放入临时寄存器, 使用2个分支,首先检查=48 但它使用的指令太多,需要额外的临时寄存器来存储48和57。还有其他有效的方法吗?是的,既然你必须减去'0',那么就这样做,然后进行无符号比较c是的,既然你必须减去'0',那么就这样做,然后进行无符号比较c我很好奇,对于c版本,我能得到什么GCC/clang;
使用2个分支,首先检查=48
但它使用的指令太多,需要额外的临时寄存器来存储48和57。还有其他有效的方法吗?是的,既然你必须减去
'0'
,那么就这样做,然后进行无符号比较c是的,既然你必须减去'0'
,那么就这样做,然后进行无符号比较c我很好奇,对于c版本,我能得到什么GCC/clang;结果没有我手写的x86 asm好,所以我写了一个答案。看起来RISC-V版本也错过了一些优化。顺便说一句,gcc/clang知道我提到的范围检查技巧;您通常不需要手动实现它。但是将它与-=“0”
结合起来转换为整数在这里很有用。
// C intentionally written exactly like hand-written asm
// Translate this to asm by hand, including the loop structure.
// or compile it if you want more bloated asm.
unsigned str_to_uint(const unsigned char *p) {
unsigned dig = *p - '0';
unsigned total = dig; // peel first iter, optimize away the + 0 * 10
if (total < 10) // <10 can share a constant with *10
goto loop_entry;
else // fall through to the uncommon case of no valid digits
return 0;
do {
total = total*10 + dig;
loop_entry: // branch target = loop entry point
dig = *++p - '0';
} while(dig < 10);
return total;
}