Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

how do I do arithmetic on the bit-strings in characters ?

Status
Not open for further replies.

NewtownGuy

Technical User
Joined
Jul 27, 2007
Messages
146
Location
US
Hello,

How do I arithmetic and logical operations on the bit strings that form characters ? How do I print the resulting bit-strings as characters ?

For example, suppose my perl code is passed value=CDEF, in other words, the four characters C, D, E and F. In general, I will only pass hex characters to perl because I want to operate on the four lsbs of each character to get a 4-bit hex value.

How do I extract the 4 lsbs from a character ?

How do I left-shift the 4 lsbs by 4 bits to do an unsigned multiply by 16 ?

How do I do a modulo-256 add of a series of 8-bit unsigned values ?

Do I have to do anything special to print the resulting 8-bit value as a character that is not likely to be a printable to the screen character since it can have any 8-bit value ?

For example, for the string CDEF above, I need to do this:

1) form an 8-bit value that is, in hex, 0xCD, from the first two characters, and a second 8-bit value that is, in hex, 0xEF, from the second two characters.

2) add 0xCD to 0xEF and get an 8-bit modulo-256 sum that is 0xBC, not 0x1BC.

3) print the byte 0xBC to a file.

Thank you.

 
Code:
[url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [blue]$char1[/blue] = [red]'[/red][purple]C[/purple][red]'[/red][red];[/red]
[black][b]my[/b][/black] [blue]$char2[/blue] = [red]'[/red][purple]D[/purple][red]'[/red][red];[/red]
[black][b]my[/b][/black] [blue]$char3[/blue] = [red]'[/red][purple]E[/purple][red]'[/red][red];[/red]
[black][b]my[/b][/black] [blue]$char4[/blue] = [red]'[/red][purple]F[/purple][red]'[/red][red];[/red]

[gray][i]# 1) form an 8-bit value that is, in hex, 0xCD, from the first two[/i][/gray]
[gray][i]# characters, and a second 8-bit value that is, in hex, 0xEF, from[/i][/gray]
[gray][i]# the second two characters.[/i][/gray]

[black][b]my[/b][/black] [blue]$val1[/blue] = [url=http://perldoc.perl.org/functions/hex.html][black][b]hex[/b][/black][/url][red]([/red][red]"[/red][purple][blue]$char1[/blue][blue]$char2[/blue][/purple][red]"[/red][red])[/red][red];[/red]
[black][b]my[/b][/black] [blue]$val2[/blue] = [black][b]hex[/b][/black][red]([/red][red]"[/red][purple][blue]$char3[/blue][blue]$char4[/blue][/purple][red]"[/red][red])[/red][red];[/red]

[gray][i]# 2) add 0xCD to 0xEF and get an 8-bit modulo-256 sum that is 0xBC,[/i][/gray]
[gray][i]# not 0x1BC.[/i][/gray]

[black][b]my[/b][/black] [blue]$result[/blue] = [red]([/red][blue]$val1[/blue] + [blue]$val2[/blue][red])[/red] [blue]%[/blue] [fuchsia]256[/fuchsia][red];[/red]
[gray][i]# warn sprintf "%x", $result; # Debug statement[/i][/gray]

[gray][i]# 3) print the byte 0xBC to a file.[/i][/gray]

[black][b]my[/b][/black] [blue]$file[/blue] = [red]'[/red][purple]temp.dat[/purple][red]'[/red][red];[/red]
[url=http://perldoc.perl.org/functions/open.html][black][b]open[/b][/black][/url][red]([/red]FILE, [red]"[/red][purple]> [blue]$file[/blue][/purple][red]"[/red][red])[/red] or [url=http://perldoc.perl.org/functions/die.html][black][b]die[/b][/black][/url] [red]"[/red][purple]Can't open [blue]$file[/blue]: [blue]$![/blue][/purple][red]"[/red][red];[/red]
[url=http://perldoc.perl.org/functions/binmode.html][black][b]binmode[/b][/black][/url][red]([/red]FILE[red])[/red][red];[/red]
[url=http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/url] FILE [url=http://perldoc.perl.org/functions/chr.html][black][b]chr[/b][/black][/url][red]([/red][blue]$result[/blue][red])[/red][red];[/red]
[url=http://perldoc.perl.org/functions/close.html][black][b]close[/b][/black][/url][red]([/red]FILE[red])[/red][red];[/red]

- Miller
 
Thank you, especially for the embedded links.

When do I need to declare variables as local using "my" ?

RE: print FILE chr($result); -- What do I do if I just want to output a byte, regardless of whether it represents a meaningful character or not ?

-- NewtownGuy
 
Is this right?:

Code:
#!/usr/bin/perl
#output a sequence of (a) sync -- an initial 8-bit whose value is always 0xFF, (b) n 8-bit values, each of which is sent to this script as two hex characters by caller, and (c) one final 8-bit value, the checksum, which is the modulo 256 sum of the n 8-bit values sent by caller, to a COM port

use CGI qw/:standard/;
$cgi = new CGI;
$value = $cgi->param('value');
print header(-status=>'204 No Content'); #dummy no-value returned to web page to avoid error messages

$bytes = length($value) / 2; #each 8-bit value to be output is sent by caller as two hex characters, so the number of bytes to be output (not counting the leading sync and trailing checksum bytes) is half the number of characters sent by caller
my $cks = 0; #initialize checksum, which will be computed as the sum of the n 8-bit values output
open(OUT, ">/dev/ttyS0"); #open output file and redirect to COM port
[COLOR=blue]binmode(OUT);[/color]
flock(OUT, 2); #lock the file to protect it from writing by others
[COLOR=blue]print OUT chr(FF); #output one fixed 8-bit value whose value is 0xFF[/color]

for ($i = 0; ($i < $bytes); $i++) { 
[COLOR=blue]my $hex1 = substr($value, (2 x $i), 1); #get m'th character
my $hex2 = substr($value, (2 x $i) + 1, 1); #get (m+1)'th character
my $hex1_hex2 = hex("$hex1$hex2"); #combine two hex characters into one byte
print OUT chr($hex1_hex2); #output one 8-bit value from two hex characters
my $cks = ($cks + $hex1_hex2) % 256; #add 8-bit value from new character to $cks. Only compute $cks to 8 bits since the calculation is modulo 256[/color]
}

[COLOR=blue]print OUT chr($cks); #output checksum as the final byte[/color]
flock(OUT, 8); #unlock the file
close(OUT);

-- NewtownGuy
 
NewtownGuy said:
When do I need to declare variables as local using "my" ?

Always. As you should always include "use strict;" at the top of every perl script.

NewtownGuy said:
RE: print FILE chr($result); -- What do I do if I just want to output a byte, regardless of whether it represents a meaningful character or not ?

Who said that chr only worked with "meaningful" characters? It's just a function. It doesn't care much about meaning. It's the same thing as:

Code:
[url=http://perldoc.perl.org/functions/pack.html][black][b]pack[/b][/black][/url] [red]"[/red][purple]C[/purple][red]"[/red], [blue]$result[/blue][red];[/red]

- Miller
 
NewtownGuy said:
Is this right?

Well, does it work? You tell us?

I'd personally format it differently. And I would probably add more error checking to determine if the data was correct. But there doesn't appear to be anything functionally wrong with your code.

Code:
[gray]#!/usr/bin/perl[/gray]
[gray][i]# output a sequence of [/i][/gray]
[gray][i]# (a) sync -- an initial 8-bit whose value is always 0xFF,[/i][/gray]
[gray][i]# (b) n 8-bit values, each of which is sent to this script as two hex[/i][/gray]
[gray][i]# characters by caller, and [/i][/gray]
[gray][i]# (c) one final 8-bit value, the checksum, which is the modulo 256 sum[/i][/gray]
[gray][i]# of the n 8-bit values sent by caller, to a COM port[/i][/gray]

[url=http://perldoc.perl.org/functions/use.html][black][b]use[/b][/black][/url] [green]CGI[/green] [red]qw/[/red][purple]:standard[/purple][red]/[/red][red];[/red]

[black][b]use[/b][/black] [green]strict[/green][red];[/red]

[url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [blue]$cgi[/blue] = new CGI[red];[/red]

[black][b]my[/b][/black] [blue]$value[/blue] = [blue]$cgi[/blue]->[maroon]param[/maroon][red]([/red][red]'[/red][purple]value[/purple][red]'[/red][red])[/red][red];[/red]

[gray][i]# Output of CGI Script[/i][/gray]
[gray][i]# - dummy no-value returned to web page to avoid error messages[/i][/gray]
[url=http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/url] [maroon]header[/maroon][red]([/red]-[purple]status[/purple]=>[red]'[/red][purple]204 No Content[/purple][red]'[/red][red])[/red][red];[/red] 
[url=http://perldoc.perl.org/functions/close.html][black][b]close[/b][/black][/url][red]([/red]STDOUT[red])[/red][red];[/red] [gray][i]# Ensure nothing else gets sent.[/i][/gray]

[gray][i]# Open output file and redirect to COM port[/i][/gray]
[url=http://perldoc.perl.org/functions/open.html][black][b]open[/b][/black][/url][red]([/red]OUT, [red]"[/red][purple]>/dev/ttyS0[/purple][red]"[/red][red])[/red] or [url=http://perldoc.perl.org/functions/die.html][black][b]die[/b][/black][/url] [red]"[/red][purple]Can't open: [blue]$![/blue][/purple][red]"[/red][red];[/red] 
[url=http://perldoc.perl.org/functions/binmode.html][black][b]binmode[/b][/black][/url][red]([/red]OUT[red])[/red][red];[/red]
[url=http://perldoc.perl.org/functions/flock.html][black][b]flock[/b][/black][/url][red]([/red]OUT, [fuchsia]2[/fuchsia][red])[/red][red];[/red] [gray][i]# Lock the file to protect it from writing by others[/i][/gray]

[gray][i]# Output one fixed 8-bit value whose value is 0xFF[/i][/gray]
[black][b]print[/b][/black] OUT [url=http://perldoc.perl.org/functions/chr.html][black][b]chr[/b][/black][/url][red]([/red][url=http://perldoc.perl.org/functions/hex.html][black][b]hex[/b][/black][/url][red]([/red][red]'[/red][purple]FF[/purple][red]'[/red][red])[/red][red])[/red][red];[/red] 

[gray][i]# each 8-bit value to be output is sent by caller as two hex characters,[/i][/gray]
[gray][i]# so the number of bytes to be output (not counting the leading sync and[/i][/gray]
[gray][i]# trailing checksum bytes) is half the number of characters sent by[/i][/gray]
[gray][i]# caller[/i][/gray]

[gray][i]# Initialize checksum, which will be computed as the sum of[/i][/gray]
[gray][i]# the n 8-bit values output[/i][/gray]
[black][b]my[/b][/black] [blue]$checksum[/blue] = [fuchsia]0[/fuchsia][red];[/red] 

[olive][b]while[/b][/olive] [red]([/red][blue]$value[/blue] =~ [red]m{[/red][purple](..)[/purple][red]}[/red][red]g[/red][red])[/red] [red]{[/red]
	[gray][i]# Combine two hex characters into one byte[/i][/gray]
	[black][b]my[/b][/black] [blue]$hexval[/blue] = [black][b]hex[/b][/black][red]([/red][blue]$1[/blue][red])[/red][red];[/red]
	
	[gray][i]# Output one 8-bit value from two hex characters[/i][/gray]
	[black][b]print[/b][/black] OUT [black][b]chr[/b][/black][red]([/red][blue]$hexval[/blue][red])[/red][red];[/red] 
	
	[gray][i]# Add 8-bit value from new character to $cks. Only compute $cks to[/i][/gray]
	[gray][i]# 8 bits since the calculation is modulo 256[/i][/gray]
	[black][b]my[/b][/black] [blue]$checksum[/blue] = [red]([/red][blue]$checksum[/blue] + [blue]$hexval[/blue][red])[/red] [blue]%[/blue] [fuchsia]256[/fuchsia][red];[/red] 
[red]}[/red]

[gray][i]# Output checksum as the final byte[/i][/gray]
[black][b]print[/b][/black] OUT [black][b]chr[/b][/black][red]([/red][blue]$checksum[/blue][red])[/red][red];[/red]

[gray][i]# Unlock the file[/i][/gray]
[black][b]flock[/b][/black][red]([/red]OUT, [fuchsia]8[/fuchsia][red])[/red][red];[/red] 
[black][b]close[/b][/black][red]([/red]OUT[red])[/red][red];[/red]
[tt]------------------------------------------------------------
Pragmas (perl 5.8.8) used :
[ul]
[li]strict - Perl pragma to restrict unsafe constructs[/li]
[/ul]
Core (perl 5.8.8) Modules used :
[ul]
[li]CGI - Simple Common Gateway Interface Class[/li]
[/ul]
[/tt]

- Miller
 
To: MillerH

Thank you, and everyone else, for your great help.

How does this statement you used work ?:

Code:
while ($value =~ m{(..)}g) {

-- NewtownGuy
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top