Reputation: 49
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
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
Reputation: 93930
shr eax, 1 ;eax is the count
shoud be sub ...
? i.e. subtract 1, not divide by 2.
Upvotes: 0