**HP Articles Forum**

[Return to the Index ]

[ Previous | Next ]

**Internet Protocol (v4) Addresses on the HP-16C**

*Posted by Cameron Paine on 20 Dec 2005, 2:36 a.m.*

An IPv4 address is simply a 32-bit unsigned integer. An address is given a sub-structure by conventional rules that divide the address pool into three classes based on numerical range. The sub-structure can be further refined by applying a 32-bit mask to the address.

Conventionally, addresses and masks are written using dotted-decimal notation. In this system, each of the four octets that make up the address (or the mask) are expressed in decimal, with a dot separating each octet. The left-hand position holds the most-significant octet.

For example:

192.168.192.42 255.255.192.0

There is an alternative notation for network masks in which a single integer, representing the number of bits that are set in the mask, is appended to a dotted-decimal address, preceded by a slash character. This is sometimes called CIDR notation. Using this scheme, the above address/mask combination would be expressed as:

192.168.192.42/18

This is a useful notation because the actual mask can be conveniently generated using the number after the slash and the 16C's left mask (MASKL) operator.

The routines in this package manipulate IPv4 addresses and network masks in various useful ways. None of the functions provided are particularly ingenious but collectively they can save quite a few keystrokes.

**User Routines**

GSB A - JOIN dotted decimal octets to 32-bit integer GSB B - SPLIT 32-bit integer to dotted decimal octets GSB C - NETwork address from CIDR GSB D - BCAST (broadcast) address from CIDR GSB E - Numnber of host ADDResses given a mask

**Service Routines**

GSB 9 - convert MASK in register 0 to CIDR form. GSB 8 - OCTET processor for SPLIT GSB 7 - convert mask in X to CIDR MASK in X

**Input and Output**

The 16C has no native dotted-decimal representation. Therefore we use the four stack registers as follows:

T := octet 3 (ms) Z := octet 2 Y := octet 1 X := octet 0 (ls)

For those functions that require CIDR addresses, the mask should be stored in Register 0. If the mask is in binary form it will be converted to CIDR form as required. Thus 192.168.192.42/26 is entered as:

26 STO 0 192 ENTER 168 ENTER 192 ENTER 42

The four octets in a returned address can be retrieved by using the roll-down key.

All routines use I for temporary storage. They may be trivially modified to use another register for that purpose. The calculator must be in unsigned decimal mode with a 32-bit word size.

; JOIN - dotted decimal octets to 32-bit integer+01 - LBL JOIN (A) +02 - R^ +03 - STO I ; I = o3 +04 - Rv +05 - X-Y ; x = o1; y = o0 +06 - [8] ; discards T +07 - RLn ; x = o1 << 8 +08 - LSTx ; bring back 8... +09 - Rv ; ...and put it in T +10 - OR ; x = o0 | o1 << 8; y = o2; z = 8; t = 8 +11 - X-Y ; x = o2 +12 - R^ ; bring back 8... +13 - SL ; ...make it 16 +14 - RLn ; x = o2 << 16 +15 - LSTx ; bring back 16... +16 - R^ ; bring back 8... +17 - OR ; ...make it 24 +18 - Rv ; x = o2 << 16; y = o0 | o1 << 8; t = 24 +19 - OR ; x = o2 << 16 | o0 | o1 << 8 +20 - RCL I ; x = o3 +21 - R^ ; x = 24 +22 - RLn ; x = o3 << 24 +23 - OR ; x = o3 << 24 | o2 << 16 | o0 | o1 << 8 +24 - RTN

; SPLIT - 32-bit integer to dotted decimal octets

+25 - LBL SPLIT (B) +26 - GSB OCTET ; do o0 +27 - Rv +28 - STO I ; stash in I +29 - R^ +30 - GSB OCTET ; do o1 +31 - Rv +32 - X-I ; stash o1, stack o0 +33 - R^ +34 - GSB OCTET ; do o2 and o3 +35 - X-Y ; x = o2; y = o3 +36 - R^ +37 - X-I ; x = o1; y = o2; z = o3 +38 - R^ ; x = o0; y = o1; z = o2; t = o3 +39 - RTN

; NET - network address from CIDR host address

+40 - LBL NET (C) +41 - GSB JOIN +42 - GSB MASK +43 - MASKL +44 - AND +45 - GTO SPLIT

; BCAST - broadcast address from CIDR network address

+46 - LBL BCAST (D) +47 - GSB JOIN +48 - GSB MASK +49 - MASKL +50 - NOT +51 - OR +52 - GTO SPLIT

; NADDR - number of host addresses on a network

+53 - LBL NADDR (E) +54 - X=0? +55 - RCL 0 +56 - X=0? +57 - RTN +58 - GSB CIDR_MASK (7) +59 - MASKL +60 - NOT +61 - [1] +62 - [-] +63 - RTN

; ; Service Routines ;

; If the high bit of X is set we assume it contains a binary ; mask and we convert it to CIDR form. Otherwise we leave it ; alone.

+64 - LBL CIDR_MASK (7) +65 - [3] +66 - [1] +67 - B? +68 - B# +69 - RTN

; Places the low-order octet of X in Y and the remaining ; high-order bits, right justified, in X.

+70 - LBL OCTET (8) +71 - [8] +72 - MASKR ; low octet mask +73 - X-Y ; swap so we stash in LSTx +74 - AND ; clear high bits +75 - LSTx ; X = word; Y = octet; +76 - [8] ; Clear low octet so we can rotate +77 - MASKR ; low octet mask... +78 - NOT ; ...becomes remaining octet mask +79 - AND ; clear low octet +80 - [8] +81 - RRn ; rotate cleared octet to MSB +82 - RTN

+83 - LBL MASK (9) +84 - RCL 0 +85 - GTO CIDR_MASK (7)

When entered into an otherwise empty 16C, with the word size set to 32 bits, [f][MEM] should show:

P - 6 r - 028

If you don't have a 16C handy and you'd like to try these out you can download the package for Nonpareil here or for my simulator here.

*Edited: 20 Dec 2005, 2:40 a.m. *