How to input a string containing between 1 and 50 characters.(Assembly) - string

;This program reverses a string.
INCLUDE Irvine32.inc
.data
aName BYTE "Abraham Lincoln",0
nameSize = ($ - aName) - 1
.code
main PROC
; Push the name on the stack.
mov ecx,nameSize
mov esi,0
L1: movzx eax,aName[esi] ; get character
push eax ; push on stack
inc esi
Loop L1
; Pop the name from the stack, in reverse,
; and store in the aName array.
mov ecx,nameSize
mov esi,0
L2: pop eax ; get character
mov aName[esi],al ; store in string
inc esi
Loop L2
; Display the name.
mov edx,OFFSET aName
call Writestring
call Crlf
exit
main ENDP
END main
I finished the first part of the problem which was making a Reverse String program but now I need to modify the program so the user can input a string containing between 1 and 50 characters. Im not to sure how to do this and was wondering if someone could help out. This is in assembly language btw

You can use ReadString from irvine32.lib. Therefor you have to change nameSize to a variable and to increase the size of aName.
I did it for you ;-) :
;This program reverses a string.
INCLUDE Irvine32.inc
.data
aName BYTE 51 DUP (?)
nameSize dd ?
.code
main PROC
mov edx, OFFSET aName
mov ecx, 50 ;buffer size - 1
call ReadString
mov nameSize, eax
; Push the name on the stack.
mov ecx,nameSize
mov esi,0
L1: movzx eax,aName[esi] ; get character
push eax ; push on stack
inc esi
Loop L1
; Pop the name from the stack, in reverse,
; and store in the aName array.
mov ecx,nameSize
mov esi,0
L2: pop eax ; get character
mov aName[esi],al ; store in string
inc esi
Loop L2
; Display the name.
mov edx,OFFSET aName
call Writestring
call Crlf
exit
main ENDP
END main

Related

nasm zero byte omitted at the end of the string

I am studying Assembly language using this nasm tutorial. Here is the code that prints a string:
SECTION .data
msg db 'Hello!', 0Ah
SECTION .text
global _start
_start:
mov ebx, msg
mov eax, ebx
; calculate number of bytes in string
nextchar:
cmp byte [eax], 0
jz finished
inc eax
jmp nextchar
finished:
sub eax, ebx ; number of bytes in eax now
mov edx, eax ; number of bytes to write - one for each letter plus 0Ah (line feed character)
mov ecx, ebx ; move the memory address of our message string into ecx
mov ebx, 1 ; write to the STDOUT file
mov eax, 4 ; invoke sys_write (kernel opcode 4)
int 80h
mov ebx, 0 ; no errors
mov eax, 1 ; invoke sys_exit (kernel opcode 1)
int 80h
It works and successfully prints "Hello!\n" to STDOUT. One thing I don't understand: it searches for \0 byte in msg, but we didn't define it. Ideally, the correct message definition should be
msg db 'Hello!', 0Ah, 0h
How does it successfully get the zero byte at the end of the string?
The similar case is in exercise 7:
; String printing with line feed function
sprintLF:
call sprint
push eax ; push eax onto the stack to preserve it while we use the eax register in this function
mov eax, 0Ah ; move 0Ah into eax - 0Ah is the ascii character for a linefeed
push eax ; push the linefeed onto the stack so we can get the address
mov eax, esp ; move the address of the current stack pointer into eax for sprint
call sprint ; call our sprint function
pop eax ; remove our linefeed character from the stack
pop eax ; restore the original value of eax before our function was called
ret ; return to our program
It puts just 1 byte: 0Ah into eax without terminating 0h, but the string length is calculated correctly inside sprint. What is the cause?

Need help concatenating two strings in 80x86 assembly language using masm

Hi im writing a program in 80x86 assembly language using masm that concatenates two strings. What I'm attempting to do is find where the end of the first string is then add the contents of the second string onto the first. Here's the code I have so far:
.586
.MODEL FLAT
.STACK 4096
INCLUDE io.h
.DATA
prompt BYTE "Input String", 0
string1 BYTE 80 DUP (?)
string2 BYTE 80 DUP (?)
displayLbl BYTE "Concatenated string", 0
.CODE
_MainProc PROC
input prompt, string1, 80 ; ask for first string
input prompt, string2, 80 ; repeat for second string
lea eax, string1
push eax
lea ebx, string2
push ebx
call strConcatenation ; procedure to concatenate the strings
add esp, 8 ; remove parameters
output displayLbl, string1 ; display result
mov eax, 0 ; exit with return code 0
ret
_MainProc ENDP
strConcatenation PROC
push ebp
mov ebp, esp
push edi
push esi
pushfd
mov edi, [ebp+8]
repnz scasb ; scan for null in string1
mov esi, [ebp+12]
dec edi
cld
whileConcStr:
cmp BYTE PTR [esi], 0 ; null source byte?
je endWhile ; stop copying if null
lodsb ; load data
stosb ; store data
jmp whileConcStr ; go check next byte
endWhile:
mov BYTE PTR [edi], 0 ; terminate destination string
popfd ; restore flags
pop esi ; restore registers
pop edi
pop ebp
ret
strConcatenation ENDP
END
When I enter strings like 'assembly' and 'language' nothing changes. Any help is appreciated, thanks.
Three bugs:
Your arguments to strConcatenation are reversed. As it stands you are concatenating string1 onto the end of string2.
repne scasb scans for the value in the al register, which you haven't initialized. To scan for nul, zero it out: xor al, al.
repne scasb terminates when the byte in al is found OR when ecx reaches zero (it is decremented on each iteration). You haven't initialized ecx either. To scan indefinitely until the byte is found, you can set ecx to -1.

replace a string in assembly

I wanna get a source string ,find a key in it and replace the key with a replace string so i copy the rest of source and the replace string in the result .
it outputs the correct prompt when the key doesnt exist in the source string : "The key does not appear in the string."
but when the source contains the key it stucks and doesnt continue running
(it looks sth in found label part have been missed and have an overflow)
can anyone help to correct the found part ?
any help will be appreciate :)
; program to search for one string embedded in another
; author: R. Detmer revised: 10/97
.386
.MODEL FLAT
ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD
INCLUDE io.h
cr EQU 0dh ; carriage return character
Lf EQU 0ah ; linefeed character
.STACK 4096 ; reserve 4096-byte stack
.DATA
prompt1 BYTE "String to search? ", 0
prompt2 BYTE cr, Lf, "Key to search for? ", 0
prompt3 BYTE cr, Lf, "Word to replace? ", 0
source BYTE 100 DUP (?)
key BYTE 20 DUP (?)
replace BYTE 20 DUP (?)
srcLength DWORD ?
keyLength DWORD ?
repLength DWORD ?
BeginLength DWORD ?
restLength DWORD ?
cpyLength DWORD ?
lastPosn DWORD ?
restPosition DWORD ?
firstParam DWORD ?
secondParam DWORD ?
keyPosition DWORD ?
failure BYTE cr,Lf,Lf,"The key does not appear in the string.",cr,Lf,0
success BYTE cr,Lf,Lf, " The result string is : " ,cr,Lf,Lf
result BYTE 200 DUP (?)
PUBLIC _start ; make entry point public
.CODE
_start: output prompt1 ; ask for
input source,100 ; and input source string
lea eax, source ; find length of string
push eax ; length parameter
call strlen
mov srcLength,eax ; save length of source
output prompt2 ; ask for
input key,20 ; and input key string
lea eax, key ; find length of string
push eax ; length parameter
call strlen
mov keyLength,eax ; save length of key
output prompt3 ; ask for
input replace,20 ; and input replace string
lea eax, replace ; find length of string
push eax ; length parameter
call strlen
dec eax
mov repLength,eax ; save length of replace
; calculate last position of source to check
mov eax,srcLength
sub eax,keyLength
inc eax ; srcLength − keyLength + 1
mov lastPosn, eax
cld ; left to right comparison
mov eax,1 ; starting position
whilePosn: cmp eax,lastPosn ; position <= last_posn?
jnle endWhilePosn ; exit if past last position
lea esi,source ; address of source string
add esi,eax ; add position
dec esi ; address of position to check is incremented automatically
lea edi,key ; address of key
mov ecx,keyLength ; number of positions to check
repe cmpsb ; check
jz found ; exit on success
inc eax ; increment position
jmp whilePosn ; repeat
endWhilePosn:
output failure ; the search failed
jmp quit ; exit
;-------------------------------------------------------------
found:
mov keyPosition, eax ; position of key
mov ebx, eax ;copy start position of key
lea eax, source
sub ebx, eax ;position - source address
mov BeginLength, ebx ;begin Source length (before key)
add ebx, keyLength
mov eax, srcLength
sub eax, ebx
mov restLength, eax ;rest of Source length (after key)
mov eax, keyPosition
add eax, keyLength ; position + key
mov restPosition, eax
;source begin to result
lea eax, result
mov firstParam, eax ; destination address
lea eax, source
mov secondParam, eax
mov eax, BeginLength ; copy length
mov cpyLength, eax
mov esi,firstParam ;initial source address
mov edi,secondParam ;destination
mov ecx ,cpyLength
rep movsb ;copy bytes
;replace to result
mov eax, firstParam
add eax , BeginLength
mov firstParam, eax ; address of rest of result
lea eax, replace
mov secondParam, eax ; string to replace
mov eax, repLength ; copy length
mov cpyLength, eax
mov esi,firstParam ;initial source address
mov edi,secondParam ;destination
mov ecx ,cpyLength
rep movsb ;copy bytes
;Rest to result
mov eax, firstParam
add eax , repLength
mov firstParam, eax ; address of rest of result
mov eax, restPosition
mov secondParam, eax
mov eax, restLength
mov cpyLength, eax
mov esi,firstParam ;initial source address
mov edi,secondParam ;destination
mov ecx ,cpyLength
rep movsb ;copy bytes
mov BYTE PTR [edi],0 ;terminate destination string
output success
quit:
INVOKE ExitProcess, 0 ; exit with return code 0
;----------------------------------------------------------
strlen PROC NEAR32
; find length of string whose address is passed on stack
; length returned in EAX
push ebp ; establish stack frame
mov ebp, esp
pushf ; save flags
push ebx ; and EBX
sub eax, eax ; length := 0
mov ebx, [ebp+8] ; address of string
whileChar: cmp BYTE PTR [ebx], 0 ; null byte?
je endWhileChar ; exit if so
inc eax ; increment length
inc ebx ; point at next character
jmp whileChar ; repeat
endWhileChar:
pop ebx ; restore registers and flags
popf
pop ebp
ret 4 ; return, discarding parameter
strlen ENDP
END
found:
mov keyPosition, eax ; position of key
mov ebx, eax ;copy start position of key
lea eax, source
sub ebx, eax ;position - source address
mov BeginLength, ebx ;begin Source length (before key)
In these lines you have subtracted things that cannot be subtracted.
When you get at the label found, EAX has a 1-based relative position index that you copy to the EBX register. This value ranges from 1 to 100. Now you subtract the absolute address of your source buffer. This could be in the millions. That's clearly a mistake. It becomes disastrous when later on you use it as a loop counter and start corrupting memory!
success BYTE cr,Lf,Lf, " The result string is : " ,cr,Lf,Lf
You forgot to zero-terminate the success message.
It will disrupt your final macro call output success and so it would seem that the program didn't correctly replace the string.

Removing a character from a string in MASM

I have to write a program that
takes a string from the key board buffer and puts it into a character array
asks for a character to remove
removes the character from the character array while shifting everything else over
I want to use a stack to accomplish this. So here is my logic.
Starting from the end of the string compare that character with the character that is to be removed. If it isn't the character push it on to the stack. If it is ignore it and move on through the string. Then starting from the beginning pop everything into place.
I'm supposed to use a procedure to accomplish this. When I'm stepping through everything seems to be working ok until I attempt to leave the procedure and return to main. I'm fairly sure my logic in my procedure is the problem. Right now when I attempt to work with the string "The" and remove the e I get "he".
TITLE String Manipulation
INCLUDE Irvine32.inc
.data
prompt byte "Please enter a string to manipulate : ",0
prompt2 byte "Please enter a character to remove: ",0
answerMSG byte "The new string is: ",0
string BYTE 51 DUP (0)
char BYTE ?
byteCount dword ?
.code
main PROC
call clrscr
push eax ;perserve the registers
push ecx
push edx
mov edx, OFFSET prompt ;prints the prompt
call writeString
mov edx, OFFSET string ;moves the register to the first location for the string
mov ecx, SIZEOF string ;Sets the max characters
call readString
mov byteCount,eax ;places actual count into a counting register
call crlf
mov edx, OFFSET prompt2 ;prints the prompt
call writeString
mov edx, OFFSET char
mov ecx, 1
call readString
call clrscr
mov ecx, byteCount
mov edx, OFFSET string
call stringMan
mov edx, OFFSET string
call writeString
pop edx
pop ecx
pop eax
main ENDP
;
stringMan PROC USES eax ecx edx
mov eax,0
L1:
movzx edx , string[ecx]
cmp dl, char
jz L2
push edx
inc eax
L2:
mov string[ecx],0
LOOP L1
mov ecx,eax
mov eax,0
L3:
pop edx
mov byte ptr string[eax],dl
inc eax
loop L3
ret
stringMan ENDP
END main
Figured it out.
Answer:
I was not dealing with getting a character from the console correctly. I also was not dealing with the case when ecx = 0. This is the first position of the character array. So I was not comparing the correct character, and not pushing the first character onto the array when necessary. I have fixed it by removing
mov edx, OFFSET char
mov ecx, 1
call readString
and replacing it with
call readChar
mov char,al
then adding this after the L1 loop.
movzx edx , string[ecx]
cmp dl,char
jz L4
push edx
inc eax
L4:
It now works as designed. I just have some formatting issues to clear up.
Answer:
I was not dealing with getting a character from the console correctly. I also was not dealing with the case when ecx = 0. This is the first position of the character array. So I was not comparing the correct character, and not pushing the first character onto the array when necessary. I have fixed it by removing
mov edx, OFFSET char
mov ecx, 1
call readString
and replacing it with
call readChar
mov char,al
then adding this after the L1 loop.
movzx edx , string[ecx]
cmp dl,char
jz L4
push edx
inc eax
L4:
It now works as designed. I just have some formatting issues to clear up.

In assembly, I want to search a string, replace a word, and display the new string

I am taking an assembly course and I have gotten most of the program written out, I am just having trouble replacing the word and displaying the new string. The problem asks for a sentence, a word to find, and a word to replace it with. The program scans the string, replaces any instances of the word, and shows you the new string.
Example: "The sky is blue."
Word to find: "sky"
Word to replace it: "ocean"
New String: "The ocean is blue."
Here is what I have so far:
.586
.MODEL FLAT
INCLUDE io.h ; header file for input/output
.STACK 4096
.DATA
prompt1 BYTE "String to Search: ", 0
prompt2 BYTE "Word to Search For: ", 0
prompt3 BYTE "Word to replace with: ", 0
target BYTE 80 DUP (?)
key BYTE 80 DUP (?)
strSub BYTE 80 DUP (?)
trgtLength DWORD ?
keyLength DWORD ?
lastPosn DWORD ?
strSubLen DWORD ?
resultLbl BYTE "The new sentence is: ", 0
.CODE
_MainProc PROC
input prompt1, target, 80 ;input target string
lea eax, target ;address of target
push eax ;parameter
call strlen ;strlen(target)
add esp, 4 ;remove parameter
mov trgtLength, eax ;save length of target
input prompt2, key, 80 ;input key string
lea eax, key ;address of key
push eax ;parameter
call strlen ;strlen(key)
add esp, 4 ;remove parameter
mov keyLength, eax ;save length of key
input prompt3, strSub, 80 ;input word to search for
lea eax, strSub ;address of key
push eax ;parameter
call strlen ;strlen(strSub)
add esp, 4 ;remove parameter
mov strSubLen, eax ;save length of key
mov eax, trgtLength
sub eax, keyLength
inc eax ;trgtLength - keyLength +1
mov lastPosn, eax
cld ;Left to Right comparison
mov eax, 1 ;starting position
whilePosn:
cmp eax, lastPosn ;position <= last_posn?
jnle endWhilePosn ;exit if past last position
lea esi, target ;address of target string
add esi, eax ;add position
dec esi ;address of position to check
lea edi, key ;address of key
mov ecx, keyLength ;number of position to check
repe cmpsb ;check
jz found ;exit of success
inc eax ;increment position
jmp whilePosn ;repeat
endWhilePosn:
output resultLbl, [esi] ;display new sentence
jmp quit
found:
sub edi, keyLength
mov ecx, strSubLen
lea esi, strSub
cld
rep movsb
inc eax
jmp whilePosn
quit:
mov eax, 0 ; exit with return code 0
ret
_MainProc ENDP
strlen PROC
push ebp ;establish stack frame
mov ebp, esp
push ebx ;save EBX
sub eax, eax ;length := 0
mov ebx, [ebp+8] ;address of string
whileChar:
cmp BYTE PTR [ebx], 0 ;null byte?
je endWhileChar ;exit if so
inc eax ;increment length
inc ebx ;point at next character
jmp whileChar ;repeat
endWhileChar:
pop ebx ;restore registers
pop ebp
ret
strlen ENDP
END
The code works as far as finding the word that I want to switch, but actually switching the words is tricking me up. The book says that the destination string should be in EDI and the word to replace should be in ESI, but the code they give as an example has the destination string in ESI, and word to replace in EDI (like I have here).
The book also does a pretty horrible job of explaining the "rep" and "movs" instructions, so I am 90% sure that my "found" code block is going to be where the problem is. Any help is much appreciated.
When dealing with strings in x86 assembly, one has to quickly master the rep instruction. If not, you will probably pass away before your first program has been completed.
A very good introduction on string manipulation in assembly can be found here (or here), but what you really need here are the following ones:
rep stosb: Store string
rep scas: Scan string
rep cmpsb: Compare string

Resources