MASM 整数转字符串

之前在QQ群里常会看到同学们做的一个题“整数转字符串”,今天还真用上了,在拼接SQL语句的时候,用sprintf效率还低呀,就想这优化优化,首先想到的就是替换掉sprintf "%d"的部分,果然效率高了不少,然后进一步我就想到了用ASM来搞搞了:

.686
.model flat, c
option casemap:none

.code

;没有跟atoi的返回值一样返回指针,而是返回字符串长度,是为了拼接方便
i2a proc uses esi edi buff:dword, val:sdword

    mov ecx, 10                    ;除数
    mov eax, val                ;被除数
    mov esi, buff                ;esi指向buff的指针

    cmp  eax, 0                    ;取绝对值
    jge  @f
    neg eax

@@:
    cdq
    idiv ecx                    ;已经是绝对值了,IDIV/DIV都可以
    add  dl, '0'                ;将数值变成字符
    mov  [esi], dl                ;然后写入字符串中
    inc  esi
    test eax, eax                ;根据商决定是否继续
    jnz  @b


    cmp  sdword ptr [val],0        ;负号
    jge  @f
    mov  byte ptr [esi], '-'
    inc  esi
@@:

    mov  byte ptr[esi], 0        ;\0结尾
    mov  eax, esi                ;返回值:字符串长度

    mov  edi, buff                ;逆序字符串
    dec  esi
@@:
    cmp edi, esi
    jge @f
    mov dl, [edi]
    mov cl, [esi]
    mov [edi], cl
    mov [esi], dl
    dec esi
    inc edi
    jmp @b
@@:

    ret
i2a endp

end
 

测试结果:

#include <stdio.h>
#include <Windows.h>
#pragma warning(disable:4996)
extern "C" unsigned int i2a(const char* buff, int val);
int main()
{
    char buff[128];
    DWORD64 start;
    char* p = NULL;
    int len = 0;
    char sql[1024];

    //方法1
    start = __rdtsc();
    for(int i = 0; i < 100000; i++)
    snprintf(sql, sizeof(sql), "insert into table1(gid,gname,age)values(%d,'%s',%d)", 33021, "demoname", 29);
    printf("%10I64d:%s\n", __rdtsc() - start, sql);

    memset(sql, 0, sizeof(sql));

    //方法2
    start = __rdtsc();
    for (int i = 0; i < 100000; i++)
    {
        memcpy(sql, "insert into table1(gid,gname,age)values(", 40);
        p = sql + 40;
        itoa(33021, buff, 10);
        len = strlen(buff);
        memcpy(p, buff, len);
        p += len;
        memcpy(p, ",'", 2);
        p += 2;
        memcpy(p, "demoname", 8);
        p += 8;
        memcpy(p, "',", 2);
        p += 2;
        itoa(29, buff, 10);
        len = strlen(buff);
        memcpy(p, buff, len);
        p += len;
        memcpy(p, ")\0", 2);
    }
    printf("%10I64d:%s\n", __rdtsc() - start, sql);

    memset(sql, 0, sizeof(sql));

    //方法3
    start = __rdtsc();
    for (int i = 0; i < 100000; i++)
    {
        memcpy(sql, "insert into table1(gid,gname,age)values(", 40);
        p = sql + 40;
        len = i2a(buff, 33021);
        memcpy(p, buff, len);
        p += len;
        memcpy(p, ",'", 2);
        p += 2;
        memcpy(p, "demoname", 8);
        p += 8;
        memcpy(p, "',", 2);
        p += 2;
        len = i2a(buff, 29);
        memcpy(p, buff, len);
        p += len;
        memcpy(p, ")\0", 2);
    }
    printf("%10I64d:%s\n", __rdtsc() - start, sql);

    return 0;
}

 101040316:insert into table1(gid,gname,age)values(33021,'demoname',29)
  10812104:insert into table1(gid,gname,age)values(33021,'demoname',29)
    6176219:insert into table1(gid,gname,age)values(33021,'demoname',29)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值