x86 assembly program to search for a word in a given text - string

I am trying to write a program using x86 assembly that can search for a word in a text. When the word is present in the text, the program will inform the user. I'm still having a problem in comparing the strings. Any advice?
.model small
.stack 200h
.data
message1 db "Enter your text here: $"
text db 150,151 dup(0)
message2 db 10,13,"Enter the word that you want to find: $"
find db 20,21 dup(0)
yesmessage db 10,13,"The word is in the text$"
nomessage db 10,13,"Sorry the word is not in the text$"
.code
Start:
;Display message and key in strings
mov ax,seg message1
mov ds,ax
mov si,offset text
mov di,offset find
mov dx,offset message1
mov ah,09h
int 21h
mov dx,si
mov ah,0Ah
int 21h
mov ax,seg message2
mov ds,ax
mov dx,offset message2
mov ah,09h
int 21h
mov dx,di
mov ah,0Ah
int 21h
;compare strings
mov bx,00
mov bl,text+1
mov bh,find+1
cmp bl,bh
jne L1
add si,2
add di,2
L2:mov bl,byte ptr[si]
cmp byte ptr[di],bl
jne L1
inc si
inc di
cmp byte ptr[di],"$"
jne L2
mov ah,09h
mov dx,offset yesmessage
int 21h
L1:mov ah,09h
mov dx,offset nomessage
int 21H
mov ax,4c00h
int 21h
end start
the expected result should be:
Example 1:
Enter your text here: He is old
Enter the word that you want to find: old
The word is in the text
Example 2:
Enter your text here: He is old
Enter the word that you want to find: young
Sorry the word is not in the text

I can see a couple of obvious problems in your code. See my comments below:
mov bx,00 ; this instruction is redundant
mov bl,text+1
mov bh,find+1
cmp bl,bh
jne L1 ; it's quite likely that the strings won't have the same length,
; i.e. that find will be shorter than text. this condition is
; therefore incorrect. it would make more sense to use jl, i.e.
; jumping to the negative print if text is shorter than find.
mov ah,09h
mov dx,offset yesmessage
int 21h
L1:mov ah,09h
mov dx,offset nomessage ; you'll be printing both messages in cases where
int 21H ; the substring is found, because you don't have
; any jump that skips past it.

Related

Need help combining two strings TASM

I need help in combining two programs I have and I can't seem to get it working for me. Don't get the desired output.
So here's my problem statement:
Combine Two separate strings in a third string and display it, Where the first String is as it is and the second string is reversed.
Example:
Input:
String 1: 'Hello'
String 2: '.dlroW '
Output:
'Hello World.'
end of Example.
Now there are two ways we can go about this.
First: Use string functions.(Preferred)
Now I am fairly new to learning Assembly Language so I would like to do it using string functions so I can learn something New.
Second: Without using string functions.
Another Approach is if someone can help combining two programs, One for the concatenation of the string and the other for reversal, Note that I have written the two individual programs and they run well without any hiccups, I just can't seem to do it together. How I am going about with this is before concatenating the string I am trying to reverse it, then proceeding with the addition of the second string. But I can't seem to get it working. I've tried to the best of my knowledge.
//Concatenation Code
.model tiny
.data
msg1 db 10,13,"Enter the string 1: $"
cat db 30 DUP('$')
msg2 db 10,13,"Enter the string 2: $"
msg3 db 10,13,"Concatenated string is: $"
.code
mov ax,#data
mov ds,ax
lea dx,msg1
mov ah,09h
int 21h
lea si,cat
up: mov ah,01h
int 21h
mov [si],al
inc si
cmp al,0dh
jnz up
lea dx,msg2
mov ah,09h
int 21h
dec si
up1: mov ah,01h
int 21h
mov [si],al
inc si
cmp al,0dh
jnz up1
lea dx,msg3
mov ah,09h
int 21h
lea dx,cat
mov ah,09h
int 21h
mov ah,4ch
int 21h
end`
Here's Part 2
//Reversal Code
.model tiny
.data
msg1 db 10,13,"enter the string: $"
string db 40 DUP('$')
rev db 40 DUP('$')
msg2 db 10,13,"reverse string is: $"
.code
mov ax,#data
mov ds,ax
lea dx,msg1
mov ah,09h
int 21h
mov ah,0ah
lea dx,string
int 21h
lea si,string
lea di,rev
mov cl,[si+1]
mov ch,00h
add di,cx
inc si
inc si
up: mov al,[si]
mov [di],al
inc si
dec di
loop up
inc di
mov ah,09h
lea dx,msg2
int 21h
mov ah,09h
lea dx,[di]
int 21h
mov ah,4ch
int 21h
end
And Here is the code I came Up with by combining those two.
//That's the code I tried Combining
.model tiny
.data
.model tiny
.data
msg1 db 10,13,"Enter string1: $"
cat db 30 DUP('$')
msg2 db 10,13,"Enter string2: $"
msg3 db 10,13,"Concatenated string is: $"
.code
mov ax, #data
mov ds,ax
lea dx,msg1
mov ah,09h
int 21h
lea si,cat
up: mov ah,01h
int 21h
mov [si],al
inc si
cmp al,0dh
jnz up
lea dx, msg2
mov ah,09h
int 21h
dec si
up2:mov al,[si]
mov [di],al
inc si
dec di
loop up2
inc di
up1:mov ah,01h
int 21h
mov [si],al
inc si
cmp al,0dh
jnz up1
lea dx,msg3
mov ah,09h
int 21h
lea dx,cat
mov ah,09h
int 21h
mov ah,4ch
int 21h
end
My Output
As you can see clearly I have failed at doing either task correctly. So can someone tell me where I am going wrong? Or teach me how to do this using the string Functions?
The up2 loop that tries to do string reversal comes too soon!. You've placed it where the 2nd string (the one that needs reversal) isn't even inputted yet.
If you would have written comments in your program, then you would probably have noticed this yourself.
This up2 loop uses the LOOP instruction that depends on the CX register but your program does not assign any suitable value to CX.
And also your working reversal program is using 2 buffers. Why then do you expect the combo to work from a single buffer?
Define the cat buffer so it can hold both strings.
Define the str buffer so it can hold the second string.
lea dx, msg1
mov ah, 09h ; DOS.PrintString
int 21h
lea di, cat
up: ; Input f i r s t string
mov ah, 01h ; DOS.GetCharacter
int 21h ; -> AL
mov [di], al
inc di
cmp al, 13
jne up
dec di ; Throw out the 13
; This marks the start of the reversed string, VERY IMPORTANT
; So don't change DI while inputting the 2nd string
lea dx, msg2
mov ah, 09h ; DOS.PrintString
int 21h
lea si, str
mov dx, si
up1: ; Input s e c o n d string
mov ah, 01h ; DOS.GetCharacter
int 21h ; -> AL
mov [si], al
inc si
cmp al, 13
jne up1
dec si ; Throw out the 13
cmp si, dx
je done ; Second string was empty. CAN HAPPEN!
up2: ; Reversed copying of s e c o n d string
dec si
mov al, [si]
mov [di], al
inc di
cmp si, dx
ja up2
done:
mov ax, 0A0Dh ; Add a proper carriage return and linefeed to the result
mov [di], ax
mov al, '$' ; Terminate the result with a dollar sign
mov [di+2], al
lea dx, msg3
mov ah, 09h ; DOS.PrintString
int 21h
lea dx, cat
mov ah, 09h ; DOS.PrintString
int 21h
First: Use string functions.(Preferred)
Both in the up loop and in the up2 loop, do you find next pair of instructions:
mov [di], al
inc di
Provided
the direction flag DF is clear so that DI can increment
the ES segment register points to #data
you can replace these 2 instructions by a single STOSB instruction.
This is what needs to go on top of your program:
.code
mov ax, #data
mov ds, ax
mov es, ax
cld
If we allowed ourselves to write a silly sequence of multiple std (set direction flag) and cld (clear direction flag) instructions, we could also replace mov al, [si] with lodsb. Care must be taken to keep a valid SI pointer (*).
dec si ; (*)
up2: ; Reversed copying of s e c o n d string
std
lodsb ; Due to STD, SI will decrement
cld
stosb ; Due to CLD, DI will increment
cmp si, dx
jae up2 ; (*)
done:
mov ax, 0A0Dh ; Add a proper carriage return and linefeed to the result
stosw
mov al, '$' ; Terminate the result with a dollar sign
stosb
In code that sets the direction flag (using std) it is best to end with a cld instruction so the direction flag is in the state we most expect!

Is there a method to CMP two strings using emu8086?

I am working on a project to organize students mark in 3 exam using assembly language.
I want the emu to CMP the user's string by the ones in the text file, so if ZF set to 1, the emu will print the hole student's information (ID, Full Name, exams marks), that came from the compassion.
Here is the code, I take help from you guys.
ORG 100H
MOV DX, OFFSET MSG1
MOV AH, 9H
INT 21H
MOV DX, OFFSET MSG2
MOV AH, 9H
INT 21H
MOV DX, OFFSET LNBF ; GET STRING FROM USER
MOV AH, 0AH
INT 21H
MOV AL, 0 ; OPEN MY FILE
MOV DX, OFFSET FILE
MOV AH, 3DH
INT 21H
; READ FROM FILE
MOV BX, AX ; MOV HANDLER TO BX
MOV CX, 1 ; READ CHAR ONE BY ONE
LEA DX, DATABF
INT 21H
RET
FILE DB "MY.txt",0
LNBF DB 1EH,?
MSG1 DB "FIND A STUDENT BY HIS/HER LAST NAME:$"
MSG2 DB 0DH,0AH,0DH,0AH,"ENTER THE STUDENT'S LAST NAME->: $"
DATABF DW 0FFFH
Do correct these errors before you continue:
LNBF DB 1EH,? does a bad job setting up a buffer to input the student's name!
It overwrites MSG1 instead of providing a decent dedicated buffer.
The correct way is : LNBF DB 30, 0, 30 dup (0)
For detailed info about the DOS.BufferedInput function 0Ah see
How buffered input works
Your READ FROM FILE code forgets to specify the required function number 3Fh.
Use mov ah, 3Fh. Also you should not neglect the possibility that an error is returned via the carry flag!
Below is an example that you can use. It compares the carriage return-terminated name in the inputbuffer with the zero-terminated name in the text file. (The file could of course be using any string terminator that suits you...)
mov si, offset LNBF + 2 ; -> SI is address of student's name.
More:
call ReadOneCharFromFile ; -> AL
cmp al, 0
je SkipToNextNameInFile
cmp al, [si]
jne SkipToNextNameInFile
inc si
cmp byte [si], 13
jne More
call ReadOneCharFromFile ; -> AL
cmp al, 0
jne SkipToNextNameInFile
MatchFound:
...
SkipToNextNameInFile:
...

String assembly

The task is to search a string and find if inputted char is in the string MES3 or not.Here is my code , but it doesn`t search all letters in the string just the first .How can i make the cycle to work and search through all symbols in the string
masm
model small
.DATA
MSG1 DB 10,13,'CHARACTER FOUND :) $'
MSG2 DB 10,13,'CHARACTER NOT FOUND :($'
MSG3 DB 10,13,'there is no hope of doing this bla : $'
MSG4 DB 10,13,'ENTER THE CHARACTER TO BE SEARCHED : $'
NEW DB 10,13,'$'
NEW1 DB 10,13,'$'
NEW2 DB 10,13,'$'
.CODE
ASSUME CS:#CODE,DS:#DATA
START:
MOV AX,#DATA
MOV DS,AX
LEA di,[MSG3]
DOWN:
LEA dx,NEW
MOV AH,09H
INT 21H
LEA DX,MSG4
MOV AH,09H
INT 21H
MOV AH,01H
INT 21H
MOV DI,0
UP1:
CMP AL,[MSG3+di]
JE DOWN3
INC DI
LOOP UP1
LEA DX,MSG2
MOV AH,09H
INT 21H
JMP FINISH
DOWN3:
LEA DX,MSG1
MOV AH,09H
INT 21H
FINISH:
INT 3
mov AX, 4c00h
int 21h
END START
The LOOP instruction (that you use in LOOP UP1) decrements CX and jumps to the target label if CX != 0. So you need to set CX to the maximum number of characters to compare before the UP1 label.
Or you could replace LOOP UP1 with CMP BYTE PTR [MSG3-1+di],'$' / JNE UP1 since the string is '$'-terminated.

Sorting strings in 8086 Assembly

I want to write a 8086 assembly program that takes 5 strings from the user as an input and then sorts these strings and prints the sorted result as an output. I actually do everything but I have a big problem with the sorting part. I know how to use a for example bubble sort to sort the items in an array that start from a specific address but here I have 5 different strings that are not in the same array. each string has its own address and its own characters. I try to compare last character of each string with each other and then if one is bigger that another one i swap the whole string and then I go on and do that for the whole characters of all string to the first.
For example if our input strings are:
eab
abe
cbd
cda
adb
I will first sort the last character of every string and I come up with this:
cda
eab
adb
cbd
abe
Then I will compare them by the middle character:
eab
cbd
abe
cda
adb
and at last with the first character and everything is sorted:
abe
adb
cbd
cda
eab
but it is actually what in my mind and I don't have any idea who to implement that for my job.
; multi-segment executable file template.
data segment
data1 db 64,?,64 dup(?)
data2 db 64,?,64 dup(?)
data3 db 64,?,64 dup(?)
data4 db 64,?,64 dup(?)
data5 db 64,?,64 dup(?)
change db 66 dup(?)
msg db 0ah,0dh,"You enter a wrong option",0ah,0dh,"try again",0ah,0dh,"$"
prompt db 0ah,0dh,"Choose an option:",0ah,0dh,"$"
prompt1 db ".a: Sort in ascending order",0ah,0dh,"$"
prompt2 db ".d: Sort in descending order",0ah,0dh,"$"
prompt3 db ".q: Quit",0ah,0ah,0dh,"$"
enter db 0ah,0ah,0dh,"Enter 5 strings:",0ah,0dh,"$"
pkey db 0ah,0dh,"press any key...$"
ends
stack segment
dw 128 dup(0)
ends
code segment
main proc far
; set segment registers:
mov ax, data
mov ds, ax
mov es, ax
again:
; printing the prompts for the user
lea dx, prompt
mov ah, 09h
int 21h
lea dx, prompt1
mov ah, 09h
int 21h
lea dx, prompt2
mov ah, 09h
int 21h
lea dx, prompt3
mov ah, 09h
int 21h
; getting a character from the user as an input
mov ah, 01h
int 21h
; determining which option the user selects
cmp al, 'a'
je ascending
cmp al, 'd'
je descending
cmp al, 'q'
je quit
; this is for the time that the user enters a wrong char
lea dx, msg
mov ah, 09h
int 21h
jmp again ; again calling the application to start
ascending:
call input
call AscendSort
jmp again ; again calling the application to start
descending:
call input
call DescendSort
jmp again ; again calling the application to start
quit:
lea dx, pkey
mov ah, 9
int 21h ; output string at ds:dx
; wait for any key....
mov ah, 1
int 21h
mov ax, 4c00h ; exit to operating system.
int 21h
main endp
;.................................................
; this subroutine gets input from user
input proc
lea dx, enter
mov ah, 09h
int 21h
call newline
mov ah, 0ah
lea dx, data1
int 21h
call newline
mov ah, 0ah
lea dx, data2
int 21h
call newline
mov ah, 0ah
lea dx, data3
int 21h
call newline
mov ah, 0ah
lea dx, data4
int 21h
call newline
mov ah, 0ah
lea dx, data2
int 21h
call newline
ret
input endp
;................................................
; sorting the strings in the ascending order
AscendSort proc
mov si, 65
lea dx, change
mov al, data1[si]
cmp al, data2[si]
ja l1
?????
ret
AscendSort endp
;................................................
; sorting the strings in the descending order
DescendSort proc
ret
DescendSort endp
;................................................
; newline
newline proc
mov ah, 02h
mov dl, 0ah
int 21h
mov dl, 0dh
int 21h
ret
newline endp
ends
end main ; set entry point and stop the assembler.
Any other algorithm for sorting these whole strings also will be appreciated.
I actually figure out the answer myself, I use string commands to compare the strings 2 by 2 with each other to see if they're bigger, smaller or equal. Something like the code below in the specific macro that takes two strings to check them and do the required operation like swapping the strings to make them sorted:
check macro a, b
local next, finish
cld
mov cx, 64 ; the size of our buffer that saves the string
mov si, a
mov di, b
repe cmpsb ; comparing two strings with each other
ja next
jmp finish
next:
; swaping our strings if needed
mov cx, 64
mov si, a
lea di, change
rep movsb
mov cx, 64
mov si, b
mov di, a
rep movsb
mov cx, 64
lea si, change
mov di, b
rep movsb
finish:
endm

search for string in file in ASSEMBLY

I need to write a program in ASSEMBLY to search for a string (input for keyboard) in all file of current folder.
What's interrupt can I use and what's algorithm of this program?
Hmm...here's some code I wrote (at least I think I wrote it -- it looks like code I'd have written, though it doesn't have any comments to confirm it) to list the files in a directory:
.model small, c
.stack
.data
file_spec db "*.*", 0
DTA db 128h dup(0)
buffer db 30 dup(0)
.code
main proc
mov ax, #Data
mov ds, ax
mov dx,offset DTA
mov ah,1Ah
int 21h ; set DTA location
mov dx,offset file_spec
xor cx, cx
mov ah,4Eh
int 21h
jc quit
print_name:
lea si, DTA + 30
next_char:
lodsb
int 29h
test al, al
jnz next_char
mov al, 13
int 29h
mov al, 10
int 29h
mov dx, offset file_spec
xor cx, cx
mov ah, 4fh
int 21h
jnc print_name
quit:
mov ax, 4c00h
int 21h
main endp
end main
Here's another that opens and displays a file:
data segment para public 'DATA'
line db 80 dup(?)
file db "test.txt"
handle dw ?
data ends
code segment para public 'CODE'
assume ds:data
assume cs:code
main proc
mov ax,data
mov ds,ax
; okay. First, open the file
mov dx,offset file
mov ax,3d00h
int 21h
mov handle,ax
read_loop:
mov dx,offset line
mov bx,handle
mov cx, 80 ; the size of our buffer.
mov ah,3fh
int 21h
jc done
test ax,ax
jz done
mov bx,1
mov cx,ax
mov dx,offset line
mov ah,40h
int 21h
jmp read_loop
done:
mov ax,4c00h
int 21h
main endp
code ends
end main
Searching for the data in the file would be basically a matter of writing a strstr in assembly language. You'd probably want to start with a quick scan using rep cmpsb and then do a byte-by-byte comparison when you find a candidate match. If that fails, you increment the position and try again.

Resources