'How to get the beginning address of a string instead of the address of a whole string
SORRY if i make you confuse about the question, but i don't know a better to describe it
i'm trying to write a NASM program to reverse a string in place.
i have 3 function: strlen, readstring, and asm_main
readstring: read from user input and store it in reserved space "inputstring"
push ebp ; setup routine
mov ebp, esp
;;;;;;;;;;;;;;;;;;;;;;;;;;
mov eax, message
call print_string ; print"please enter your string message"
mov eax, 3 ; read
mov ebx, 1 ; from standard input
mov ecx,inputstring; store at memory locaton inputstring
mov edx, 100 ; 100 byte
int 0x80
mov eax, inputstring
;;;;;;;;;;;;;;;;;;;;;
pop ebp
ret
Later, i use another subprogram "strlen" to get the length of users' input
The problem is:
In my main program, i have two register hold the address of the beginning and the last char. so ecx holds begin, ebx holds last char
let's say i type "abcde",
so i have $ecx point to the beginning of the string, and $ebx point to the last char(which is e\n). My question is, when i swaping ecx and ebx, am i swapping the whole string(abcde) with the last char(e/n)?
or am i swaping the first char(a) with the last char(e/n)?
when i try to print out the content of each register in GDB.
ecx: abede/n
ebx: e/n
so i'm swaping the whole string with the last char, which is definitely not i want. So where did i do wrong??? can someone pls give me a hint?
Here is my code
%include "asm_io.inc"
segment .data
message db "Please enter your string message: ", 0xA,0
formatin db "%d", 0xA
segment .bss
inputstring: resb 100
segment .text
global asm_main
extern printf
extern scanf
**asm_main**:
enter 0, 0
pusha
;;;;;;;;;;;;;;;;;;;;;;;;
call readstring
mov ecx, eax ; now ecx contains the begin address
call strlen ; when return, eax will hold the length
push eax ; we need eax in the loop
; use edi as temporary pointer
; use ebx to point to the last char
mov ebx, 0 ;initialize ebx to 0
add ebx, ecx ; ebx = ecx now, ebx points to the beginning
add ebx, eax ; ebx = ecx + eax, now it points to then end
sub ebx, 1 ; ebx = ecx +eax -1, now it points to the
; last char
while:
cmp ebx, ecx ; cmp end , begining
jle exitWhile
mov edi, [ebx] ; temp = *end
mov eax,[ecx] ; *end = *begining
mov [ebx], eax
mov [ecx], edi ; *beginning = temp
inc ecx
dec ebx
jmp while
exitWhile:
pop eax
popa
mov eax, 0
leave ; missing this line will cause segmentation
; fault, why?
ret
**readstring**:
push ebp ; setup routine
mov ebp, esp
;;;;;;;;;;;;;;;;;;;;;;;;;;
mov eax, message
call print_string
mov eax, 3 ; read
mov ebx, 1 ; from standard input
mov ecx,inputstring; store at memory locaton inputstring
mov edx, 100 ; 100 byte
int 0x80
mov eax, inputstring
;;;;;;;;;;;;;;;;;;;;;
pop ebp
ret
**strlen**:
push ebp
mov ebp, esp
push esi
;;;;;;;;;;;;;;;;;;;;;
mov esi, ecx ; now esi contains the address of string
mov edx, 0 ; edx will be int i
loop:
mov al, [esi] ; al
cmp al, 0xA ; check if al holds an ASCII new line
je exitLoop
inc esi
inc edx
cmp esi, inputstring+100; see if esi is pointing past the end
; of the 100 reserved byte
jl loop
exitLoop:
;;;;;;;;;;;;;;;;;;;;
mov eax, edx
pop esi
pop ebp
ret
Solution 1:[1]
You are swapping four characters at a time since you are using 32-bit registers for the job. You swap "abcd" with "e\n??" (where ?? are the two bytes after your string). Use an 8-bit register for ASCII characters:
while:
cmp ebx, ecx ; cmp end , beginning
jbe exitWhile ; while (end > start) {
mov al,[ebx]
xchg al,[ecx] ; extremely slow: atomic RMW + full memory barrier
mov [ebx],al
inc ecx
dec ebx
jmp while ; }
exitWhile:
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Peter Cordes |