OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 5:09 am

All times are UTC - 6 hours




Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 12 posts ] 
Author Message
 Post subject: How do I compare a string?
PostPosted: Wed Jan 11, 2017 3:32 pm 
Offline
Member
Member

Joined: Wed Jan 11, 2017 3:29 pm
Posts: 27
Hey guys. I am trying to compare a string. I am wanting to make a shell with commands.
For example, if I type clear, it will clear the screen.

I've tried INT 16 and cmp but it hasn't worked.
How would I make it so if I type a command and press enter, it would do something.

Thanks
John


Top
 Profile  
 
 Post subject: Re: How do I compare a string?
PostPosted: Wed Jan 11, 2017 3:41 pm 
Offline
Member
Member
User avatar

Joined: Tue Jan 10, 2017 3:19 pm
Posts: 84
TheDev100 wrote:
Hey guys. I am trying to compare a string. I am wanting to make a shell with commands.
For example, if I type clear, it will clear the screen.

I've tried INT 16 and cmp but it hasn't worked.
How would I make it so if I type a command and press enter, it would do something.

Thanks
John


About the question itself:

Let's assume what the user typed is in EAX, and we're using intel syntax (destination, source).

Code:
cmp eax, 'clear'
je clearscreen



This code compares eax (assuming it contains something like 'clear') and if equal/succesful, it jumps to the label clearscreen where you can later clear the screen and reinitialize the shell.

Hope this works,

Dixium

_________________
(not so frequently updated) Code is at:

https://github.com/NunoLava1998/DixiumOS-1


Top
 Profile  
 
 Post subject: Re: How do I compare a string?
PostPosted: Wed Jan 11, 2017 3:45 pm 
Offline
Member
Member

Joined: Wed Jan 11, 2017 3:29 pm
Posts: 27
Thanks man :D but is it possible for this to be 16-bit and also give me an example of how to do the other part?
I mean the part when you type in clear and press enter then it clears the screen.


Top
 Profile  
 
 Post subject: Re: How do I compare a string?
PostPosted: Wed Jan 11, 2017 3:50 pm 
Offline
Member
Member
User avatar

Joined: Tue Jan 10, 2017 3:19 pm
Posts: 84
TheDev100 wrote:
Thanks man :D but is it possible for this to be 16-bit and also give me an example of how to do the other part?
I mean the part when you type in clear and press enter then it clears the screen.


It is 16bit-compatible so real-mode operating systems can do this. However, change eax to ax (eax is only for 32bit and 64bit and later)

I don't know about the typing part (get user's character, append it to (e)ax and when enter is the last character, don't append the enter and see if the command is available. otherwise, print a error)

About the clear screen part, you can switch graphics mode to your current graphics mode (in 80x25 text operating systems, 3) to do that.

_________________
(not so frequently updated) Code is at:

https://github.com/NunoLava1998/DixiumOS-1


Top
 Profile  
 
 Post subject: Re: How do I compare a string?
PostPosted: Wed Jan 11, 2017 3:50 pm 
Offline
Member
Member

Joined: Wed Jun 17, 2015 9:40 am
Posts: 501
Location: Athens, Greece
Hi,


The string "clear" takes 5 bytes (or 6, if NUL terminator is accounted for), while eax can hold only 4 bytes. You need a string comparison function that takes two pointers as input and traverses the strings pointed to.

I suggest you first learn before giving advice.


Regards,
glauxosdever


Top
 Profile  
 
 Post subject: Re: How do I compare a string?
PostPosted: Wed Jan 11, 2017 3:53 pm 
Offline
Member
Member
User avatar

Joined: Tue Aug 02, 2016 1:52 pm
Posts: 286
Location: East Riding of Yorkshire, UK
I think that there's an example on the wiki - Real mode assembly I

_________________
com.sun.java.swing.plaf.nimbus.InternalFrameInternalFrameTitlePaneInternalFrameTitlePaneMaximizeButtonWindowNotFocusedState
Compiler Development Forum


Top
 Profile  
 
 Post subject: Re: How do I compare a string?
PostPosted: Wed Jan 11, 2017 8:10 pm 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

TheDev100 wrote:
Hey guys. I am trying to compare a string. I am wanting to make a shell with commands.
For example, if I type clear, it will clear the screen.

I've tried INT 16 and cmp but it hasn't worked.
How would I make it so if I type a command and press enter, it would do something.


The simplest approach is to store it in memory somewhere, then have a loop that compares each character in one string with the character in the same position in the other string.

The first improvement would be to use "rep cmpsb" to compare characters (and there are ways to speed it up a lot more with SSE/AVX if you're into that).

This is possibly fine if you only need to do one string comparison; however you're going to have more than one command so you're typically going to need to do more than one string comparison.

For your case (multiple commands/strings that are static/known in advance) the next improvement would be to use the length of the input string to find a list of command strings that have the same length. For example, if the user types "hello" then you might use "length = 5" to find a list that contains "clear" and any other 5 letter commands and avoid comparing against any command strings that have different lengths ("dir" and "exit" and "echo" and...) and make it a lot faster. Of course that's still not fast.

For your case, the fastest/best way would be to implement a finite state machine using a tree. The basic idea here is that you have a root table that has an addresses for each letter, where that address determines where to find a child table. Then if the user types "c" you use the entry corresponding to "c" to find the child table for all commands that begin with "c". Then if the user types "l" you use the entry (in the child table) to find the next child (the root table's grandchild) which would be used for all commands that begin with "cl". When the user presses enter, you already know which command it is so you can start doing that command immediately without doing any string comparisons.

Not only is this so fast that it's virtually instantaneous, you can avoid the need for storing the string in memory. It also means that you can implement "auto-complete" efficiently - e.g. if the user types "cl" and there's only one command that begins with those letters ("clear") then it'd be trivial to guess that the command will be "clear" and let the user press (e.g.) the tab key to auto-complete it (and let the user avoid typing the remaining 3 characters themselves).

Note that as performance increases, both complexity and code size tend to increase too. This is fairly normal - there's always a compromise between "slower" and "more complex and larger".


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: How do I compare a string?
PostPosted: Wed Jan 18, 2017 12:05 pm 
Offline
Member
Member

Joined: Sat Nov 21, 2009 5:11 pm
Posts: 852
DixiumOS wrote:
Let's assume what the user typed is in EAX, and we're using intel syntax (destination, source).

Code:
cmp eax, 'clear'
je clearscreen



This code compares eax (assuming it contains something like 'clear') and if equal/succesful, it jumps to the label clearscreen where you can later clear the screen and reinitialize the shell.

Hope this works,

Dixium

What is this I don't even


Top
 Profile  
 
 Post subject: Re: How do I compare a string?
PostPosted: Wed Jan 18, 2017 1:05 pm 
Offline
Member
Member

Joined: Thu May 19, 2011 5:13 am
Posts: 228
DixiumOS wrote:
TheDev100 wrote:
Hey guys. I am trying to compare a string.
Code:
cmp eax, 'clear'
je clearscreen
Hope this works
glauxosdever wrote:
The string "clear" takes 5 bytes (or 6, if NUL terminator is accounted for), while eax can hold only 4 bytes.
You need a string comparison function that takes two pointers as input and traverses the strings pointed to.
I suggest you first learn before giving advice.
Gigasoft wrote:
What is this I don't even
While his advice is not technically correct, it is none the less an old school technique.
Code:
  mov esi, buffer
  xor eax, eax
  mov esi, buffer
  mov edi, esi
  stosd ; clear buffer to all zeros
; get user input and limit to 4 ascii characters
  lodsd ; esi points to user input string
  or eax, 0x20202020 ; convert to lower case
; and pad less than 4 character input with spaces for comparison
  cmp eax, 'clea' ; r screen
  je clear_screen
  cmp eax, 'time'
  je get_time
  cmp eax, 'xxx '
  je show_pomography
; ... and so on

Beware of the homoglyph in show_pomography.

[edit - corrected code example]

_________________
Mike Gonta
look and see - many look but few see

https://mikegonta.com


Last edited by mikegonta on Thu Jan 19, 2017 1:54 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: How do I compare a string?
PostPosted: Thu Jan 19, 2017 10:11 am 
Offline
Member
Member

Joined: Sat Mar 01, 2014 2:59 pm
Posts: 1146
DixiumOS wrote:
Let's assume what the user typed is in EAX, and we're using intel syntax (destination, source).

Code:
cmp eax, 'clear'
je clearscreen



This code compares eax (assuming it contains something like 'clear') and if equal/succesful, it jumps to the label clearscreen where you can later clear the screen and reinitialize the shell.
That is literally THE worst string comparison function that I have ever seen. Note that character literals are not the same as string literals and that strings are arrays of integer values with each element containing the ASCII code of the respective character in the string. It is standard practice to pass a pointer to (i.e. the memory address of) these arrays around in registers. This is not the same as storing the string itself in a register. Once you understand that registers are fixed sizes and that strings can have any number of characters in them, it should be fairly to understand why we don't store strings themselves in registers.

_________________
When you start writing an OS you do the minimum possible to get the x86 processor in a usable state, then you try to get as far away from it as possible.

Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing


Top
 Profile  
 
 Post subject: Re: How do I compare a string?
PostPosted: Thu Jan 19, 2017 10:23 am 
Offline
Member
Member
User avatar

Joined: Thu Mar 10, 2016 7:35 am
Posts: 167
Location: Lancaster, England, Disunited Kingdom
onlyonemac wrote:
That is literally THE worst string comparison function that I have ever seen. Note that character literals are not the same as string literals and that strings are arrays of integer values with each element containing the ASCII code of the respective character in the string. It is standard practice to pass a pointer to (i.e. the memory address of) these arrays around in registers. This is not the same as storing the string itself in a register. Once you understand that registers are fixed sizes and that strings can have any number of characters in them, it should be fairly to understand why we don't store strings themselves in registers.


Slightly unfair (though the code being discussed has one or two little difficulties like trying to use stos with esi instead of edi).

There are situations where holding a complete string in eax might make sense, if for example you were searching a list of small, fixed length codes such as the 3 letter ISO country codes or the table of elements.


Top
 Profile  
 
 Post subject: Re: How do I compare a string?
PostPosted: Thu Jan 19, 2017 1:52 pm 
Offline
Member
Member

Joined: Thu May 19, 2011 5:13 am
Posts: 228
onlyonemac wrote:
DixiumOS wrote:
Let's assume what the user typed is in EAX, and we're using intel syntax (destination, source).
Code:
cmp eax, 'clear'
je clearscreen
This code compares eax (assuming it contains something like 'clear') and if equal/succesful, it jumps to the label clearscreen where
you can later clear the screen and reinitialize the shell.
That is literally THE worst string comparison function that I have ever seen. Note that character literals are not the same as string
literals and that strings are arrays of integer values with each element containing the ASCII code of the respective character in the
string. It is standard practice to pass a pointer to (i.e. the memory address of) these arrays around in registers. This is not the same
as storing the string itself in a register. Once you understand that registers are fixed sizes and that strings can have any number of
characters in them, it should be fairly to understand why we don't store strings themselves in registers.
MichaelFarthing wrote:
Slightly unfair (though the code being discussed has one or two little difficulties like trying to use stos with esi instead of edi).
The code that you are referring to is not the same code as referred to by onlyonemac, however his critique applies equally well to both.
The stos business is in my code (which I threw in at the last moment) in my example. I'm not a big fan of such instructions (although I was
recently doing some 8086 boot sector programming (where every byte counts). I've corrected the example and thank you for pointing it out.
What's the "other little difficulty"?
Getting back to onlyonemac's critique - I fully agree, however in the problem solving realm, it's best to approach such thing without
preconceived notions however correct those notions may be.

_________________
Mike Gonta
look and see - many look but few see

https://mikegonta.com


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 12 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 29 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group