user2252004
user2252004

Reputation: 49

Calling assembly code with C, errors in output

I am working on a program in C that takes in a string and prints out the same string reversed by calling a function written in assembly.

My C code is:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

// These functions will be implemented in assembly:
//
void strrev(char *str) ;

int main(){
    char *str1;
    str1 = strdup("Hello World");
    strrev(str1);
    printf("str1 reversed: \"%s\"\n", str1) ;
    free(str1);
    return 0;
}

And my .asm file is:

; File: strrev.asm
; A subroutine called from C programs.
; Parameters: string A
; Result: String is reversed and returned.


    SECTION .text
    global strrev
_strrev: nop
strrev:
    push    ebp
    mov ebp, esp

    ; registers ebx,esi, and edi must be saved if used
    push ebx
    push edi

    xor esi, esi    
    xor eax, eax
    mov ecx, [ebp+8]    ; load the start of the array into ecx
    jecxz   end     ; jump if [ecx] is zero
    ;mov    edi, ecx


mainLoop:
    add     eax, 1  ;inc eax would work as well
    add ecx, 1  
    mov dl, [ecx]
    cmp     dl, 0   ; compare current ecx with 0
    je  reverseLoop ;if ecx is 0, we are done
    jmp mainLoop    ;if ecx isnt 0, keep looping

reverseLoop:
    mov     ecx, [ebp+8]    ;reload the start of the arrary into ecx
    mov esi, ecx    ; esi poinst to start of array
    add ecx, eax
    mov edi, ecx
    dec edi     ;edi points to end of array
    shr eax, 1      ;eax is the count
    jz  end     ;if string is 0 or 1 chars long, jump to end

reverseLoop_1:

    mov cl, [esi]   ;load start of array into cl
    mov bl, [edi]   ;load end of array into bl
    mov [esi], bl   ;swap
    mov [edi], al   
    inc esi
    dec edi
    dec eax     ;loop
    jnz reverseLoop_1

end:
    pop     edi     ;restore registers
    pop     ebx         
    mov esp, ebp    ;take down stack frame
    pop ebp
    ret

The program runs successfully, but the output is:

str1 reversed: "dlroW "

Where after the first word, the second part "Hello" is printed as bytes (5 squares with numbers in each corner). What would cause this?

Upvotes: 0

Views: 222

Answers (3)

raj raj
raj raj

Reputation: 1922

You gave

mov [edi], al 

instead of

mov [edi], cl 

in reverseLoop_1

Upvotes: 1

LSerni
LSerni

Reputation: 57453

reverseLoop:
    mov     ecx, [ebp+8]    ;reload the start of the arrary into ecx
    mov esi, ecx    ; esi points to start of array
    add ecx, eax    ;
    mov edi, ecx    ;
    dec edi         ;edi points to end of array
    shr eax, 1      ;eax is the count
    jz  end         ;if string is 0 or 1 chars long, jump to end

reverseLoop_1:
    mov cl, [esi]   ;load start of array into cl
    mov bl, [edi]   ;load end of array into bl
    mov [esi], bl   ;swap
    mov [edi], al   ; AL?!? Should it not be CL?
    inc esi         ;
    dec edi         ; 
    dec eax         ;loop
    jnz reverseLoop_1

In the above, you read in CL, but then store AL.

I'd do it like this, and do without the check on eax altogether:

    mov edi, ecx    ;
    dec edi         ;edi points to end of array
reverseLoop_1:
    cmp esi, edi    ; when esi >= edi we're done.
    jae finished    ; 
    mov cl, [esi]   ;load start of array into cl
    mov bl, [edi]   ;load end of array into bl
    mov [esi], bl   ;swap
    mov [edi], cl   ;
    inc esi         ;
    dec edi         ;
    jmp reverseLoop_1
 finished:

Upvotes: 1

Ben Jackson
Ben Jackson

Reputation: 93930

shr eax, 1 ;eax is the count shoud be sub ...? i.e. subtract 1, not divide by 2.

Upvotes: 0

Related Questions