// File: /workspace/github_c_makefile_star2_O0/nilyang[P]redis-tdd-annotation/src/bitops.c
// Function: bitcountCommand
void bitcountCommand(redisClient *c) {
    robj *o;
    long start, end, strlen;
    unsigned char *p;
    char llbuf[32];

    /* Lookup, check for type, and return 0 for non existing keys. */
    // 查找 key
    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||
        checkType(c,o,REDIS_STRING)) return;

    /* Set the 'p' pointer to the string, that can be just a stack allocated
     * array if our string was integer encoded. */
    // 检查对象的编码，并在有需要时转换值的类型
    if (o->encoding == REDIS_ENCODING_INT) {
        p = (unsigned char*) llbuf;
        strlen = ll2string(llbuf,sizeof(llbuf),(long)o->ptr);
    } else {
        p = (unsigned char*) o->ptr;
        strlen = sdslen(o->ptr);
    }

    /* Parse start/end range if any. */
    // 如果给定了 start 和 end 参数，那么读入它们
    if (c->argc == 4) {
        if (getLongFromObjectOrReply(c,c->argv[2],&start,NULL) != REDIS_OK)
            return;
        if (getLongFromObjectOrReply(c,c->argv[3],&end,NULL) != REDIS_OK)
            return;
        /* Convert negative indexes */
        if (start < 0) start = strlen+start;
        if (end < 0) end = strlen+end;
        if (start < 0) start = 0;
        if (end < 0) end = 0;
        if (end >= strlen) end = strlen-1;
    } else if (c->argc == 2) {
        /* The whole string. */
        start = 0;
        end = strlen-1;
    } else {
        /* Syntax error. */
        addReply(c,shared.syntaxerr);
        return;
    }

    /* Precondition: end >= 0 && end < strlen, so the only condition where
     * zero can be returned is: start > end. */
    if (start > end) {
        // 超出范围的 case ，略过
        addReply(c,shared.czero);
    } else {
        long bytes = end-start+1;

        // 遍历数组，统计值为 1 的位的数量
        addReplyLongLong(c,redisPopcount(p+start,bytes));
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x8(%rax), %rsi
leaq 0x9bd4d(%rip), %rax     # 0x114150
movq 0x20(%rax), %rdx
callq 0x3c0c0
movq %rax, -0x10(%rbp)
cmpq $0x0, %rax
je 0x7842a
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
xorl %edx, %edx
callq 0x3abb0
cmpl $0x0, %eax
je 0x7842f
jmp 0x785cb
movq -0x10(%rbp), %rax
movl (%rax), %eax
shrl $0x4, %eax
andl $0xf, %eax
cmpl $0x1, %eax
jne 0x78466
leaq -0x50(%rbp), %rax
movq %rax, -0x30(%rbp)
leaq -0x50(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdx
movl $0x20, %esi
callq 0x39660
cltq
movq %rax, -0x28(%rbp)
jmp 0x78483
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x770a0
movq %rax, -0x28(%rbp)
movq -0x8(%rbp), %rax
cmpl $0x4, 0x30(%rax)
jne 0x7853b
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x10(%rax), %rsi
leaq -0x18(%rbp), %rdx
xorl %eax, %eax
movl %eax, %ecx
callq 0x3b960
cmpl $0x0, %eax
je 0x784b8
jmp 0x785cb
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x18(%rax), %rsi
leaq -0x20(%rbp), %rdx
xorl %eax, %eax
movl %eax, %ecx
callq 0x3b960
cmpl $0x0, %eax
je 0x784df
jmp 0x785cb
cmpq $0x0, -0x18(%rbp)
jge 0x784f2
movq -0x28(%rbp), %rax
addq -0x18(%rbp), %rax
movq %rax, -0x18(%rbp)
cmpq $0x0, -0x20(%rbp)
jge 0x78505
movq -0x28(%rbp), %rax
addq -0x20(%rbp), %rax
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x18(%rbp)
jge 0x78514
movq $0x0, -0x18(%rbp)
cmpq $0x0, -0x20(%rbp)
jge 0x78523
movq $0x0, -0x20(%rbp)
movq -0x20(%rbp), %rax
cmpq -0x28(%rbp), %rax
jl 0x78539
movq -0x28(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x78576
movq -0x8(%rbp), %rax
cmpl $0x2, 0x30(%rax)
jne 0x7855b
movq $0x0, -0x18(%rbp)
movq -0x28(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x78574
movq -0x8(%rbp), %rdi
leaq 0x9bbea(%rip), %rax     # 0x114150
movq 0x80(%rax), %rsi
callq 0x35a70
jmp 0x785cb
jmp 0x78576
movq -0x18(%rbp), %rax
cmpq -0x20(%rbp), %rax
jle 0x78596
movq -0x8(%rbp), %rdi
leaq 0x9bbc5(%rip), %rax     # 0x114150
movq 0x20(%rax), %rsi
callq 0x35a70
jmp 0x785cb
movq -0x20(%rbp), %rax
subq -0x18(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x58(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x30(%rbp), %rdi
addq -0x18(%rbp), %rdi
movq -0x58(%rbp), %rsi
callq 0x770e0
movq -0x60(%rbp), %rdi
movq %rax, %rsi
callq 0x36480
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)