Search code examples
cstringassemblyx86att

counting the '0's in a string in assembly


I have a little program written with c and assembly. the principle is simple: "count the '0's in a a string given by main.c

so for test0 str0ing 0 it should return 3 because there's 3 '0's in the string the function itself is made in x86 asm with AT&T syntax, i am given a pointer to the string via C. both main.c and the asm is linked via header file.

this is my code so far and the problem is that it always returns 0. it never reaches conditional jump to increment %eax(to be returned)

// C

#include "asm.h"

char string[] = "2a0 a0 ";
char *ptr1 = string;

int main(){
    
    printf("\nthere are : %d %s in :%s", zero_count(), "0s", string);
    printf("\nstring address is: %p\n", ptr1);
    
    return 0;
}

// x86asm

    .global ptr1

.section .text
    .global zero_count          #func()
    

zero_count:

    # prologue
    pushl %ebp              # save these previous stack frame pointer
    movl %esp, %ebp         # the stack frame pointer for function
    
    # save registers
    #pushl $ebx             # needs to be pushed out of stack when used
    #pushl %esi             # needs to be pushed out of stack when used
    #pushl %edi             # needs to be pushed out of stack when used
    
    # function body
    movl ptr1, %ecx         # moves the value of ptr1 to ecx
    movl $0, %eax           # cleans eax with 0
                    
    # loop start
    loop_beginning:
        cmp $0, (%ecx)
        je end
        
        # compare to 'o'
        cmp $48, %ecx       # 48 is "0" in the asci table
        je if_0
        
        increment_pointer:
            addl $1, %ecx
            jmp loop_beginning
        
        if_0:
            addl $1, %eax
            jmp increment_pointer
            
    end:
    #popl %edi              # needs to be popped when used
    #popl %esi              # needs to be popped when useds
    #popl %ebx              # needs to be popped when used
    
    # epilogue
    movl %ebp, %esp         # restore the previous stack pointer("cleaner" the stack)
    popl %ebp               # restore the previous stack frame pointer
    ret                     #w returns

i apolagize for using global variables in advance, i know it's not good but I'm still learning to use the stack


Solution

  • by switching the cmp to cmpb worked in this string. but i still don't know why. would this operation also worked if this was an int[]?

        .global ptr1
    
    .section .text
        .global zero_count          #func()
        
    
    zero_count:
    
        # prologue
        pushl %ebp              # save these previous stack frame pointer
        movl %esp, %ebp         # the stack frame pointer for function
        
        # save registers
        #pushl $ebx             # needs to be pushed out of stack when used
        #pushl %esi             # needs to be pushed out of stack when used
        #pushl %edi             # needs to be pushed out of stack when used
        
        # function body
        mov ptr1, %ecx          # moves the value of ptr1 to ecx
        movl $0, %eax           # cleans eax with 0
                        
        # loop start
        loop_beginning:
            cmpb $0, (%ecx)
            je end
            
            # compare to 'o'
            cmpb $48, (%ecx)        # 48 is "0" in the asci table
            je if_0
            
            increment_pointer:
                addl $1, %ecx
                jmp loop_beginning
            
            if_0:
                addl $1, %eax
                jmp increment_pointer
                
        # movl (%ecx), %eax
        
        end:
        #popl %edi              # needs to be popped when used
        #popl %esi              # needs to be popped when useds
        #popl %ebx              # needs to be popped when used
        
        # epilogue
        movl %ebp, %esp         # restore the previous stack pointer("cleaner" the stack)
        popl %ebp               # restore the previous stack frame pointer
        ret                     #w returns