Contributor: SWAG SUPPORT TEAM { > How does the following Function make a Word into Hex: - Dissection: } Type Str4 : String[4]; Function WordtoHex(W : Word) : St4 Var HexStr : St4; Function Translate(B : Byte) : Char; { This Function takes a number from 0 to 15 and makes it into a hex digit.} begin if B < 10 then { if it's 0..9 } Translate := Chr(B + 48) { These statements use math on Characters... ascii 48 is '0'. Could have been written: Translate := Chr(B + ord('0')) } else Translate := Chr(B + 55); { This one is For letters A~F. ascii 55 isn't anything, but if you add $A (10) to 55 you get 65, which is the ascii code For 'A' This could have been written: Translate := Chr(B + ord('A')-$A); } end; begin HexStr := ' '; HexStr := HexStr + Translate(Hi(W) shr 4); { Hi(W) takes the high Byte of Word W. shr 4 means the same as divide by 16... What they're Really doing here is taking each nibble of the hex Word and isolating it, translating it to hex, and adding it to the String. } HexStr := HexStr + Translate(Hi(W) and 15); HexStr := HexStr + Translate(Lo(W) shr 4); HexStr := HexStr + Translate(Lo(W) and 15); WordtoHex := HexStr; end; { > I am learning Pascal and don't understand something. How > does the following Function make a Word into Hex: It doesn't, at least not as present! But if you changes two things, maybe spelling-errors, it will work. This is a bit hard to explain and grasp, because it involves operations at a less abstract level than the one that you usually work on in TP. Remember, when a number is stored in memory, it's stored binary, hexadecimal notion is just For making it easier For man to read. I don't know if you know how to Write and read binary- and hexadecimal-numbers, in Case you don't know it's all here... On PC, a Word, in the range 0 to 65535, has 16 bits. A Word written in binary notion For this reason contains 16 digits, 0's or 1's! But a Word written in hexadecimal notion contains 4 digits. Simple math tells us that one digit in hex-notion is equal to four digits binary. Four digits binary gives 16 combinations (2^4). ThereFore, each hexadecimal digit must be able to contain values from decimal 0-decimal 15, _in one digit_! Our normal digits, 0-9, isn't sufficient For this, we must use 6 other digits. The designers of this system choosed A-F as the extra digits. This means, in hex the digits are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E and F. Hanging on? > Function WordtoHex(W : Word) : St4 Compile-time error: You must have a semicolon after the Function header-line. > Var > HexStr : St4; > Function Translate(B : Byte) : Char; > begin > if B < 10 > then > Translate := Chr(B + 48) > else > Translate := Chr(B + 55); > end; This is clearer as: if b < 10 then Translate := Chr(b+ord('0')) else Translate := Chr(b+ord('A')-10); Think about the first Case, when b < 10, if b were 0, the expression would be '0' plus 0, '0'!. if b were 1, it's '0' plus 1, '1'!. This works because in the ASCII-table the numbers are sequential ordered. But '0' plus 10 would be ':', because it happens to be after the numbers. then, when we want 'A'-'F, we would need to start from 'A'. But we can't add 10 to 'A' For getting 'A' and 11 For getting 'B' and that like. First we must make the value relative 'A'. Because the values that we're working on here is in the range 10 to 15, we can decrease it With 10 and get 0 to 5. then is OK to use them relative 'A'. As beFore, 'A' plus 0 is 'A', 'A' plus 1 is 'B', and so on. However, this routine has no safety check, it will gladly return 'G' For 16, because 'A'+6 is 'G'. It doesn't care if the value is within hexadecimal range or not (numbers bigger than 15 can't be turned into one hex digit, they need more digits). But here it's OK, because the routine is local to WordtoHex that will never pass anything else than 0 to 15. > begin > HexStr := ' '; Logical error: You must initalize HexStr to an empty String, '', if not it will consist of a space and three hex digits, not four. A hex-Word String is Composed of four hexadeciamal-digits. Because you have declared the String as a Variable of the Type St4 and St4 only allows four Chars, exactly what is needed For a hexWord-String, the last one added will be discarded if you have a space at the beginning, filling up one position. > HexStr := HexStr + Translate(Hi(W) shr 4); > HexStr := HexStr + Translate(Hi(W) and 15); > HexStr := HexStr + Translate(Lo(W) shr 4); > HexStr := HexStr + Translate(Lo(W) and 15); > WordtoHex := HexStr; > end; It would be easier to read if the 'and'-value were in hex-notation, $000F. See below For explanation why. However, this part requires some understanding of the bits. It's probably best show With an example. Let's say, our number W is $1234. $1234 is written 0001 0010 0011 0100 in binary. Each hex-digit corresponds to a four-group binary digits. þ) The binary number 0001 is 0*(2^3) + 0*(2^2) + 0*(2^1) + 1*(2^0). It gives 0+0+0+1=1 in decimal. þ) The binary number 0101 is 0*(2^3) + 1*(2^2) + 0*(2^1) + 1*(2^0). It gives 0+4+0+1=5 in decimal. þ The _decimal_ number 1101 is 1*(10^3) + 1*(10^2) + 0*(10^1) + 1*(10^0). It gives 1000+100+0+1=1011! As you can see, the only difference between the decimal and the binary and the hexadecimal system is the base-power. True, the hex-system Uses strange digits For us used to decimal, but For the ones used to binary, 2-9 is equally strange... Like our decimal system, in hex and binary, it's unnescessary to include leading zeros, i. e. $0001 = $1 (of course you can't remove trailing zeroes, decimal 1000 certainly isn't equal to decimal 1...). But you will note that I sometimes include these leading zeroes, just because it looks good (?). and writing binary number 1000 0000 is like writing 10000 in decimal as 10,000; it's only For easy reading, but the Compiler won't allow it. However, I hope you grasp a least something of my extremly bad explanation :-(, or maybe you know it beFore?! Now, let's look at the things that happens when the above statements are executed and w = $1234 (0001 0010 0011 0100). Hi returns the upper 8 bits of the Word, in this Case 0001 0010; Lo returns the lower bits (!), 0011 0100. The above code Uses 'and' and 'shr', a breif explanation of them will probably be nescessary (oh no :-)). þ and, when not used as a Boolean operator, Uses two binary numbers and, For each bit, tests them. if _both_ bits are set (equal to 1) the resuling bit is set to 1, if any or both of them is cleared (equal to 0) the result is 0. This means: 0001 0010 Hi(w) 0011 0100 Lo(w) 0000 1111 and With 15 or $000F 0000 1111 and With 15 or $000F --------- --------- 0000 0010 0010 binary = 2 hex 0000 0100 0100 binary = 4 hex This was the second and first statement, and out you get the second and first number! When we pass them to Translate, we get back '2' and '4'. þ shr, only For binary operations, shifts the bits to the right. The bits that passes over the right side is lost, and the ones that move on left side is replaced by zeroes. The bits shifts as many times as the value after the shr-keyWord, here 4 times. Like this: 00010010 Hi(w) 00110100 Lo(w) -------- shr 4 -------- 00001001 after one shift 00011010 00000100 after two shifts 00001101 00000010 after three shifts 00000110 00000001 after four shifts 00000011 Now we got binary 0001 and binary 0011, in hex $1 and $3. The first and third statement, and the first and third number! The String to return is digit1 + digit2 + digit3 + digit4, exactly what we want. Hmm... Now I haven't told you anything about the binary or, xor, not and shl-keyWords... But I think this message is quiet long as it is, without that. But if you want more info or a better explanation, only drop me a msg here. Happy hacking /Jake 930225 17.35 (started writing last night) PS. There may be some errors, I haven't proof-read the Text or my math. then, please correct me, anybody. }