SWAGOLX.EXE (c) 1993 GDSOFT ALL RIGHTS RESERVED 00043 BITWISE TRANSLATIONS ROUTINES 1 05-28-9313:53ALL SWAG SUPPORT TEAM BITS1.PAS IMPORT 14 ₧8┴ {π Sean Palmerππ> What if I want to just access a bit? Say I have a Byte, to storeπ> Various access levels (if it does/doesn't have this, that, or theπ> other). How can Iππ> 1) Access, say, bit 4?π> 2) Give, say, bit 4, a value of 1?ππ> I have a simple routine that does "GetBit:= Value SHR 1;" to returnπ> a value, but how can I *SET* a value? And is the above a goodπ> method? I only have TP5.5, so I can't do the Asm keyWord (yet..).ππYou COULD use TP sets to do it...π}ππTypeπ tByte = set of 0..7;πVarπ b : Byte;ππ{to get:π Write('Bit 0 is ',Boolean(0 in tByte(b)));ππto set:π tByte(b):=tByte(b)+[1,3,4]-[0,2];π}ππTypeπ bitNum = 0..7;π bit = 0..1;ππFunction getBit(b : Byte; n : bitNum) : bit;πbeginπ getBit := bit(odd(b shr n));πend;ππFunction setBit( b : Byte; n : bitNum) : Byte;πbeginπ setBit := b or (1 shl n);πend;ππFunction clrBit(b : Byte; n : bitNum) : Byte;πbeginπ clrBit := b and hi($FEFF shl n);πend;ππ{π OR.....using Inline() code (the fastest)π These are untested but I'm getting fairly good at assembling by hand...8)π}ππFunction getBit(b : Byte; n : bitNum) : bit;πInline(π $59/ {pop cx}π $58/ {pop ax}π $D2/$E8/ {shr al,cl}π $24/$01); {and al,1}ππFunction setBit(b : Byte; n : bitNum) : Byte;πInline(π $59/ {pop cx}π $58/ {pop ax}π $B3/$01/ {mov bl,1}π $D2/$E3/ {shl bl,cl}π $0A/$C3); {or al,bl}ππFunction clrBit(b : Byte; n : bitNum) : Byte;πInline(π $59/ {pop cx}π $58/ {pop ax}π $B3/$FE/ {mov bl,$FE}π $D2/$C3/ {rol bl,cl}π $22/$C3); {or al,bl}π 2 05-28-9313:53ALL SWAG SUPPORT TEAM BITS2.PAS IMPORT 25 ₧8!5 {πROB GREENππ> What if I want to just access a bit? Say I have a Byte, to storeπ> Various access levels (if it does/doesn't have this, that, or theπ> other). How can Iπ> 1) Access, say, bit 4?π> 2) Give, say, bit 4, a value of 1?ππHeres a Procedure i wrote to handle all that. if you need speed, thenπi suggest to manually check each bit, rather than use the Procedures.ππ(these Procedures are based on 1, not 0. thus each Byte is like so:π87654321 instead of 76543210. to change to 0 base, change the Array toπ[0..31] instead of [1..32].)ππto set a bit: (b is an Integer Type, BIT is which bit to setπ b:=b or BIT; ex: b:=b or 128 (set bit 8)ππto clear a bit:π b:=b and not BIT; ex:b:=b and not 8; (clears bit 4)ππto check a bit:π if b and BIT<>0 then.. ex:if b and 64 then.. (check bit 7)π}ππConstπ{ Used to convert the Bit value to the actual corresponding number }π bit : Array[1..32] of LongInt =π (1, 2, 4, 8, $10, $20, $40, $80, $100, $200, $400, $800, $1000, $2000,π $4000, $8000, $10000, $20000, $40000, $80000, $100000, $200000,π $400000, $800000, $1000000, $2000000, $4000000, $8000000, $10000000,π $20000000, $40000000, $80000000);ππ{b is which bit to set(1-32), size is the size of temp.πUse SIZEOF(TEMP) to get the value, and temp is the actuall Integer basedπnumberπreturns True if bit set, False if not}ππFunction checkbit(b : Byte; size : Byte; Var temp) : Boolean; {1-32}πVarπ c : Boolean;πbeginπ c:=False;π Case size ofπ 1 : c := Byte(temp) and bit[b] <> 0; {Byte,shortint}π 2 : c := Word(temp) and bit[b] <> 0; {Word,Integer}π 4 : c := LongInt(temp) and bit[b] <> 0; {LongInt}π elseπ Writeln('Invalid size');π end;π checkbit := c;πend;ππ{b,size,and temp same as above. if onoff =True the bit will be set,πelse the bit will be cleared}ππProcedure setbit(b : Byte; onoff : Boolean; size : Byte; Var temp); {1-32}πbeginπ if onoff thenπ Case size ofπ 1 : Byte(temp) := Byte(temp) or bit[b]; {Byte}π 2 : Word(temp) := Word(temp) or bit[b]; {Word}π 4 : LongInt(temp) := LongInt(Temp) or bit[b]; {LongInt}π elseπ Writeln('Invalid size');π endπ elseπ Case size ofπ 1 : Byte(temp) := Byte(temp) and not bit[b]; {Byte}π 2 : Word(temp) := Word(temp) and not bit[b]; {Word}π 4 : LongInt(temp) := LongInt(Temp) and not bit[b];{LongInt}π elseπ Writeln('Invalid size');π end;πend;ππ{this is a sample test Program i wrote For you to see how to use theπstuff above}ππVarπ i : LongInt;π j : Byte;πbeginπ i := 0;π setbit(4,True,sizeof(i),i); {8}π Writeln(i);π setbit(9,True,sizeof(i),i); {256+8 = 264}π Writeln(i);π setbit(9,False,sizeof(i),i); {8}π Writeln(i);π setbit(20,True,sizeof(i),i); { $80000+8 = $80008}π Writeln(i);π For i := 65550 to 65575 doπ beginπ Write(i : 8, ' = ');π For j := 32 downto 1 do {to print right}π if checkbit(j, sizeof(i), i) thenπ Write('1')π elseπ Write('0');π Writeln;π end;πend.π 3 05-28-9313:53ALL SWAG SUPPORT TEAM BIT_GET.PAS IMPORT 3 ₧8Ñ' { You can use multiplies of 2 like: }ππFunction Find_Bit(B, c : Byte) : Byte;π{c is the position c=0 far right c=7 far leftπreturns 0 or 1}πbeginπ if b MOD (b shl c) = 0 then Find_Bit := 0π else Find_Bit := 1πend;ππ 4 05-28-9313:53ALL SWAG SUPPORT TEAM BIT_ROT1.PAS IMPORT 8 ₧8à╨ The commands you need to rotate a Byte/Word are:ππROR, ROL, RCR, RCL.πROR ==> Rotates the bits the number of times specified, so that theπ rightmost bits are rotated into the leftmost bits. NO BITSπ ARE LOST. ROL is the same thing in the opposite direction.ππRCR ==> Practically the same as the ROR/ROL instruction, but it rotatesπ the bit into the carry, and the carry bit is rotated into theπ leftmost bit of the Byte/Word. {Rotate right through carry}π RCL is the same in the other direction.ππThe format For each of ROR,ROL,RCR,RCL,SHR,SHL isππ [Instruction] <Destination> <Shift Count>ππTo reWrite your original code:ππAsmπ Mov AL, ByteVarπ Ror AL, 1π Mov ByteVar, ALπendππThe above would rotate the bits in the Variable ByteVar by one to the right.π 5 05-28-9313:53ALL CHRIS PRIEDE Rotate Bits LEFT/RIGHT IMPORT 14 ₧8G > I made a Program in Turbo-Pascal that rotates the bits in one Byte so I canπ> encrypt/decrypt a File, however the routine is slow. I then made the sameπ> Program in turbo-C using _RotLeft and _RotRight, the speed of execution wasπ> Really faster than Turbo-Pascal. Does anybody know of a way to rotate theπ> bits of one Byte in turbo-Pascal and FAST !!!!πππ Since 80xxx CPUs have bit rotate instructions (ROL, ROR), it wouldπbe a shame to use some clumsy HLL Construct. BTW, I'm sure _RotLeft andπ_RotRight use rotate instructions too, possibly insert them Inline. Ifπyou are using TP 6.0+, try something like this:ππ{ to rotate left }πFunction RotLeft(B, Count: Byte): Byte; Assembler;πAsmπ mov al, Bπ mov cl, Countπ rol al, clπend;ππ{ to rotate right }πFunction RotRight(B, Count: Byte): Byte; Assembler;πAsmπ mov al, Bπ mov cl, Countπ ror al, clπend;πππ Of course, if you need to do this in only a few places it wouldπbe better not to define Functions, but insert Asm blocks in your codeπdirectly.ππ The fastest Pascal way to rotate Byte would be something likeπthis:ππFunction RotLeft(B, Count: Byte): Byte;πVarπ W : Word;π A : Array[0..1] of Byte Absolute W;πbeginπ A[0] := B;π A[1] := B;π W := W shl Count;π RotLeft := A[1];πend;ππ To rotate right With this method, you would shift right andπreturn A[0]. I would like to think this is as fast as it gets in TPπwithout assembly, but one can never be sure <g>. Anyway, I recommendπthe assembly solution over this one, it is faster and more elegant.π 6 05-28-9313:53ALL SWAG SUPPORT TEAM BIT_ROT3.PAS IMPORT 5 ₧8¬ {πSEAN PALMERπ}ππFunction rolW(b : Word; n : Byte) : Word; Assembler;πAsmπ mov ax, bπ mov cl, nπ rol ax, clπend;ππFunction rolB(b, n : Byte) : Byte; Assembler;πAsmπ mov al, bπ mov cl, nπ rol al, clπend;ππFunction rolW1(b : Word) : Word; Assembler;πAsmπ mov ax, bπ rol ax, 1πend;ππ{ These would be better off as Inline Functions, such as... }ππFunction IrolW1(b : Word) : Word;πInline(π $58/ {pop ax}π $D1/$C0); {rol ax,1}ππ{ because no Function call is generated. }ππ 7 05-28-9313:53ALL SWAG SUPPORT TEAM BYT2REAL.PAS IMPORT 5 ₧8Ç, Typeπ bsingle = Array [0..3] of Byte;ππ{ converts Microsoft 4 Bytes single to TP Real }ππFunction msb_to_Real (b : bsingle) : Real;πVarπ pReal : Real;π r : Array [0..5] of Byte Absolute pReal;πbeginπ r [0] := b [3];π r [1] := 0;π r [2] := 0;π move (b [0], r [3], 3);π msb_to_Real := pReal;πend; { Function msb_to_Real }ππ{πAnother Turbo Pascal routine to convert Microsoft single to TP LongIntππindex := ((mssingle and not $ff000000) or $00800000) shr (24 -π((mssingle shr 24) and $7f)) - 1;π}π 8 05-28-9313:53ALL SWAG SUPPORT TEAM BYTE2BIN.PAS IMPORT 7 ₧8"a {πByte to Binary...π}ππTypeπ String8 = String[8];πππFunction Byte2Bin(byTemp : Byte) : String8;πVarπ Count : Integer;πbeginπ Byte2Bin[0] := #8;π For Count := 0 to 7 doπ Byte2Bin[8 - Count] := Char(((byTemp shr Count) and 1) + ord('0'));πend;ππFunction Byte2BinAsm(byTemp : Byte) : String8; Assembler;πAsmπ push dsπ les di,@resultπ mov ah,byTempπ mov cl,8π mov al,clπ stosbπ@loop:π mov al,24π add ah,ahπ adc al,alπ stosbπ loop @loopπ pop dsπend;ππbeginπ Writeln;π Writeln('10 in Binary = ',Byte2Bin(10));π Writeln;π Writeln('The same thing With assembly code: ',Byte2BinAsm(10));π Writeln;π Readln;πend. 9 05-28-9313:53ALL SWAG SUPPORT TEAM BYTEINFO.PAS IMPORT 57 ₧8⌐└ {π>Also, how would I simply read each bit?π}π{ Test if a bit is set. }πFunction IsBitSet(Var INByte : Byte; Bit2Test : Byte) : Boolean;πbeginπ if (Bit2Test in [0..7]) thenπ IsBitSet := ((INByte and (1 shl Bit2Test)) <> 0)π elseπ Writeln('ERROR! Bit to check is out of range!');πend; { IsBitSet. }ππ{π>How on earth can I manipulate an individual bit?ππ...One method is to use the bit-operators: AND, OR, XOR, NOTπ}ππ{ Manipulate an individual BIT within a single Byte. }πProcedure SetBit(Bit2Change : Byte; TurnOn : Boolean; Var INByte : Byte);πbeginπ if Bit2Change in [0..7] thenπ beginπ if TurnOn thenπ INByte := INByte or (1 shl Bit2Change)π elseπ INByte := INByte and NOT(1 shl Bit2Change);π end;πend; { SetBit. }ππ{π>...but I'm not sure exactly what the shifting is doing.π}ππ { Check if the bit is to be turned on or off. }π If TurnOn thenππ {π SHL 1 (which has a bit map of 0000 0001) to the bitπ position we want to turn-on.ππ ie: 1 SHL 4 = bit-map of 0001 0000ππ ...Then use a "logical OR" to set this bit.ππ ie: Decimal: 2 or 16 = 18π Binary : 0000 0010 or 0001 0000 = 0001 0010π }ππ INByte := INByte or (1 shl Bit2Change)π elseππ {π Else turn-off bit.ππ SHL 1 (which has a bit map of 0000 0001) to the bitπ position we want to turn-off.ππ ie: 1 SHL 4 = bit-map of 0001 0000ππ ...Then use a "logical NOT" to flip all the bits.ππ ie: Decimal: not ( 16 ) = 239π Binary : not (0001 0000) = (1110 1111)ππ ...Than use a "logical AND" to turn-off the bit.ππ ie: Decimal: 255 and 239 = 239π Binary : 1111 1111 and 1110 1111 = 1110 1111π }ππ INByte := INByte and NOT(1 shl Bit2Change);ππ{π>Also, how can you assign a Byte (InByte) a Boolean value (OR/AND/NOT)ππ or / xor / and / not are "logical" bit operators, that can be use onπ "scalar" Types. (They also Function in the same manner For "Boolean"π logic.)ππ>If I have, say 16 bits in one Byte, the interrupt list says that forπ>instance the BIOS calls (INT 11), AX is returned With the values. Itπ>says that the bits from 9-11 tell how many serial portss there are.π>How do I read 3 bits?ππ To modify the two routines I posted wo work With 16 bit Variables,π you'll need to change:ππ INByte : Byte; ---> INWord : Word;ππ ...Also:ππ in [0..7] ---> in [0..15]ππ ...If you don't want to use the IsBitSet Function listed aboveπ (modified to accept 16-bit Word values) you could do the followingπ to check if bits 9, 10, 11 are set in a 16-bit value:ππ The following is the correct code For reading bits 9, 10, 11π of the 16-bit Variable "AX_Value" :ππ Port_Count := ((AX_Value and $E00) SHR 9);ππ NOTE: Bit-map For $E00 = 0000 1110 0000 0000ππ ...If you've got a copy of Tom Swan's "Mastering Turbo Pascal",π check the section on "logical operators".πππ{π>Var Regs : Registers;π>beginπ> Intr($11,Regs);π> Writeln(Regs.AX);π>end.ππ>How do I manipulate that to read each bit (or multiple bits likeπ>the number of serial ports installed (bits 9-11) ?π}ππUsesπ Dos;ππVarπ Port_Count : Byte;π Regs : Registers;ππbeginπ Intr($11, Regs);π Port_Count := ((Regs.AX and $E00) SHR 9);π Writeln('Number of serial-ports = ', Port_Count)πend.π{πNOTE: The hex value of $E00 is equivalent to a 16-bit value withπ only bits 9, 10, 11 set to a binary 1. The SHR 9 shifts theπ top Byte of the 16-bit value, to the lower Byte position.π}π{π>Is $E00 the same as $0E00 (ie, can you just omit leading zeros)?ππYeah, it's up to you if you want to use the leading zeros or not.ππThe SHR 9 comes in because once the value has been "AND'd" withπ$E00, the 3 bits (9, 10, 11) must be placed at bit positions:π0, 1, 2 ...to correctly read their value.ππFor example, say bits 9 and 11 were set, but not bit 10. If weπ"AND" this With $E00, the result is $A00.ππ1011 1010 0111 1110 and 0000 1110 0000 0000 = 0000 1010 0000 0000π ^ ^π(bits 9,11 are set) and ( $E00 ) = $A00π...Taking the result of $A00, and shifting it right 9 bit positionsππ $A00 SHR 9 = 5ππ 0000 1010 0000 0000 SHR 9 = 0000 0000 0000 0101ππ...Which evalutates to 5. (ie: 5 serial ports)π}ππππππππππ{πGet Equipment Bit-Mapπ---------------------ππ AH ALπ 76543210 76543210πAX = ppxgrrrx ffvvmmciππ...π...πrrr = # of RS232 ports installedπ...π...ππ (* reports the number of RS232 ports installed *)πFunction NumRS232 : Byte;πVar Regs : Registers; (* Uses Dos *)πbeginπ Intr($11,Regs);π NumRS232 := (AH and $0E) shr 1;πend;πππ...When you call Int $11, it will return the number of RS232 ports installedπin bits 1-3 in register AH.ππFor example if AH = 01001110 , you can mask out the bits you *don't* wantπby using AND, like this:ππ 01001110 <--- AHπ and 00001110 <---- mask $0Eπ ──────────────π 00001110 <---- after maskingπππThen shift the bits to the right With SHR,ππ 00001110 <---- after maskingπ SHR 1 <---- shift-right one bit positionπ ─────────────π 00000111 <---- result you wantπ}ππ{π-> How do I know to use $4 For the third bit? Suppose I want to readπ-> the fifth bit. Do I simply use b := b or $6?ππ Binary is a number system just like decimal. Let me explain.πFirst, consider the number "123" in decimal. What this means,πliterally, isππ1*(10^2) + 2*(10^1) + 3*(10^0), which is 100 + 20 + 3.ππ Binary works just the same, however instead of a 10, a 2 is used asπthe base. So the number "1011" meansππ1*(2^3) + 0*(2^2) + 1*(2^1) + 1*(2^0), or 8+0+2+1, or 11.ππ This should make it clear why if you wish to set the nth bit toπTrue, you simply use a number equal to 2^(n-1). (The -1 is thereπbecause you probably count from 1, whereas the powers of two, as you mayπnote, start at 0.)ππ-> b or (1 SHL 2) Would mean that b := 1 (True) if b is already equal toπ-> one (1) and/OR the bit two (2) to the left is one (1) ???ππ Aha. You are not familiar With bitwise or operations. When oneπattempts to or two non-Boolean values (Integers), instead of doing aπlogical or as you are familiar with, each individual BIT is or'd. I.E.πimagine a Variables A and B had the following values:ππa := 1100 (binary);πb := 1010 (binary);ππthen, a or b would be equal to 1110 (binary); Notice that each bit of aπhas been or'd With the corresponding bit of b? The same goes For and.πHere's an example.ππa := 1100 (binary);πb := 1010 (binary);ππa and b would be equal to 1000;ππI hope this clears up the confusion. And just to be sure, I'm going toπbriefly show a SHL and SHR operation to make sure you know. Considerπthe numberππa := 10100 (binary);ππThis being the number, A SHL 2 would be equal to 1010000 (binary) --πnotice that it has been "shifted to the left" by 2 bits.ππA SHR 1 would be 1010 (binary), which is a shifted to the right by 2πbits.π}ππ 10 05-28-9313:53ALL SWAG SUPPORT TEAM DEC2BIN1.PAS IMPORT 6 ₧8Q▓ {π> I need to transfer decimal into binary using TURBO PASCAL.π> One way to do this is to use the basic algorithm, dividingπ> by 2 over and over again. if the remainder is zero theπ> bit is a 0, else the bit is a 1.π>π> However, I was wondering if there is another way to convertπ> from decimal to binary using PASCAL. Any ideas?ππAs an 8-bit (ie. upto 255) example...π}ππ Function dec2bin(b:Byte) : String;π Var bin : String[8];π i,a : Byte;π beginπ a:=2;π For i:=8 downto 1 doπ beginπ if (b and a)=a then bin[i]:='1'π else bin[i]:='0';π a:=a*2;π end;π dec2bin:=bin;π end;ππ 11 05-28-9313:53ALL SWAG SUPPORT TEAM DEC2BIN2.PAS IMPORT 7 ₧8₧è { True so here is another version of the process that returns a String : }ππProgram Dec2BinRec;ππTypeπ Str32 = String[32];ππFunction Dec2BinStr(aNumber : LongInt) : Str32;ππ Function Bit(aBit : Byte) : Char;π (* return either Char '0' or Char '1' *)π beginπ if aBit = 0 thenπ Bit := '0'π elseπ Bit := '1'π end;ππbeginπ If aNumber = 0 Thenπ Dec2BinStr := '' (* done With recursion ?*)π else (* convert high bits + last bit *)π Dec2BinStr := Dec2BinStr(ANumber Div 2) + Bit(aNumber Mod 2);πend;ππVarπ L : LongInt;πbeginπ Repeatπ Readln (L);π If L <> 0 thenπ Writeln(Dec2BinStr(L));π Until (L = 0)πend.π 12 05-28-9313:53ALL SWAG SUPPORT TEAM HEX2BIN1.PAS IMPORT 22 ₧8/ Function Hex2Bin (B : Byte) : String;ππVarπ Temp : String [8];π Pos, Mask : Byte;ππbeginπ Temp := '00000000';π Pos := 8;π Mask := 1;π While (Pos > 0) Doπ beginπ if (B and Mask)π thenπ Temp [Pos] := '1';π Dec (Pos);π Mask := 2 * Mask;π end;π Hex2Bin := Temp;πend;ππππππππFunction Hex2Bin( HexByte:Byte ):String; External; {$L HEX2Bin.OBJ}πVar i : Integer;πbeginπ For i := $00 to $0F do WriteLn( Hex2Bin(i) );πend.π(*********************************************************************)ππ The Assembly source ...ππ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;πcode segment Byte 'CODE' ; HEX2Bin.Asmπ assume cs:codeπ; Function Hex2Bin( HexByte :Byte ) :String;πString equ dWord ptr [bp+6]πHexByte equ [bp+4]π public Hex2BinπHex2Bin proc Near ; link into main TP Programπ push bp ; preserveπ mov bp,sp ; stack frameπ les di, String ; result String Pointerπ cld ; Forward scanπ mov cx,8 ; 8 bits in a Byteπ mov al,cl ; to setπ stosb ; binary String lengthπ mov ah, HexByte ; get the hex Byteπ h2b: xor al,al ; cheap zeroπ rol ax,1 ; high bit to low bitπ or al,'0' ; make it asciiπ stosb ; put it in Stringπ loop h2b ; get all 8 bitsπ pop bp ; restoreπ ret 2 ; purge stack & returnπHex2Bin endpπcode endsπ endπ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ππ Here's the assembled OBJ File ...ππ Put all of this remaining message in a Text File named HEX2Bin.SCR,π then Type "DEBUG < HEX2Bin.SCR" (no quotes) to create HEX2Bin.ARC;π then extract HEX2Bin.OBJ using PKUNPAK or PAK ...π ---------------------------- DEBUG script ----------------------------π N HEX2Bin.ARCπ E 0100 1A 02 48 45 58 32 42 49 4E 2E 4F 42 4A 00 5E 65 00 00 00 4A 19π E 0115 13 22 60 F2 65 00 00 00 80 0D 00 0B 68 65 78 32 62 69 6E 2E 41π E 012A 53 4D A9 96 07 00 00 04 43 4F 44 45 44 98 07 00 20 1D 00 02 02π E 013F 01 1F 90 0E 00 00 01 07 48 45 58 32 42 49 4E 00 00 00 6A 88 04π E 0154 00 00 A2 01 D1 A0 21 00 01 00 00 55 8B EC C4 7E 06 FC B9 08 00π E 0169 8A C1 AA 8A 66 04 32 C0 D1 C0 0C 30 AA E2 F7 5D C2 02 00 21 8Aπ E 017E 02 00 00 74 1A 00π Rcxπ 0084π Wπ Qπ ----------------------------------------------------------gbug-1.0b--π 13 05-28-9313:53ALL SWAG SUPPORT TEAM HEXCONV.PAS IMPORT 7 ₧8x╟ Varπ n : Word;π long : LongInt;ππFunction Byte2Hex(numb : Byte): String; { Converts Byte to hex String }π Constπ HexChars : Array[0..15] of Char = '0123456789ABCDEF';π beginπ Byte2Hex[0] := #2;π Byte2Hex[1] := HexChars[numb shr 4];π Byte2Hex[2] := HexChars[numb and 15];π end; { Byte2Hex }ππFunction Numb2Hex(numb: Word): String; { Converts Word to hex String.}π beginπ Numb2Hex := Byte2Hex(hi(numb))+Byte2Hex(lo(numb));π end; { Numb2Hex }ππFunction Long2Hex(L: LongInt): String; { Converts LongInt to hex String }π beginπ Long2Hex := Numb2Hex(L shr 16) + Numb2Hex(L);π end; { Long2Hex }πππbeginπ long := 65536;π n := 256;π Writeln(Long2Hex(long));π Writeln(Numb2Hex(n));πend.π 14 05-28-9313:53ALL SWAG SUPPORT TEAM HEXINFO.PAS IMPORT 13 ₧8Φó > I am learning Pascal and don't understand something. How does theπ> following Function make a Word into Hex:ππ It's Really doing two things, it's converting a binary valueπ into ascii, and from decimal to hex. Let's start With theπ calling or main part of the Program. You're taking a 2 Byteπ Word and breaking it up into 4 nibbles of 4 bits each. Each ofπ these nibbles is displayed as a Single hex Character 0-F.ππ Hex Representation XXXXπ ||||π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);--------------|πππNow the translate Function simply converts the decimal value ofπthe 4-bit nibble into an ascii hex value. if you look at anπascii Chart you will see how this is done:ππ'0' = 48 '5' = 53 'A' = 65π'1' = 49 '6' = 54 'B' = 66π'2' = 50 '7' = 55 'C' = 67π'3' = 51 '8' = 56 'D' = 68π'4' = 52 '9' = 57 'E' = 69π 'F' = 70πππAs you can see it easy For 0-9, you just add 48 to the value andπit's converted, but when you go to convert 10 to A, you need toπuse a different offset, so For values above 9 you add 55.ππFunction Translate(B : Byte) : Char;π beginπ if B < 10 thenπ Translate := Chr(B + 48)π elseπ Translate := Chr(B + 55);π end;π 15 05-28-9313:53ALL SWAG SUPPORT TEAM RANDOM1.PAS IMPORT 15 ₧8{ {Another method to acComplish this (which only requires an order of nπitterations is to generate an Array initialized from 2 to 1000 and thenπrandomize that Array. For your 400 numbers, just take 400 values in theπnew sequence (starting at the index of your lowest number). You can doπthat as follows:π}ππConst MaxNumber = 2000;πType SeqArray = Array [1..MaxNumber] of Integer;ππ{================================================================}πProcedure RandomizeSeq (first, last: Integer; Var iseq: SeqArray);π{================================================================}ππVar i, iran,π temp, imax : Integer;π r : Real;π{π Operation: A random number within the range 1..last is generatedπ on each pass and the upper limit of the random number generated isπ decreased by 1. The value stored at the highest index of the lastπ pass is moved to the location of the last number selected.ππ Parameters:π first = lowest number in sequence.π last = highest number in sequence.π iseq = Sequence Arrayπ}πbeginπ { initialize sequence Array }π For i := first to last do iseq[i] := i;π Randomize;π { randomize the sorted Array }π For imax := last downto first do beginπ { get a random number between 0 and 1 and scale up toπ an Integer in the range of first to last }π r := random;π iran := Trunc(r*imax) + first;π { replace With value at highest index }π temp := iseq[iran];π iseq[iran] := iseq[imax];π iseq[imax] := tempπ end;πend;ππ{ Example of generating 20 random numbers from 2 to 100: }ππVar i : Integer;π a : SeqArray;πbeginπ RandomizeSeq(2,100,a);π For i := 2 to 21 do Write(a[i]:3); Writeln;πend.π 16 05-28-9313:53ALL SWAG SUPPORT TEAM RANDOM2.PAS IMPORT 18 ₧8└| { MR> I have started playing With Borland Turbo Pascal 7.0 and I have aπ MR> problem. The Random routine is not the same as the one in TP 6.0.π MR> Using the same RandSeed, they generate different series of numbers.π MR> I have a couple of applications that depend upon the number seriesπ MR> generated by the TP 6.0 version. Can anyone supply me With theπ MR> algorithm used in the TP 6.0 Random routine? or maybe point me inπ MR> the right direction? I want to Construct my own TP 7 Random routineπ MR> that will behave as the one in TP 6.ππThe way both generators work is to update System.Randseed, then calculate theπnew random value from that one. There have been several different ways toπcalculate the value; I think TP 6 is different from TP 5.5, and TP 7 isπdifferent again. The update algorithm has been pretty Constant.ππAs I recall, you can simulate the TP 6 Random(N) Function in TP 7 as follows:π}πFunction TP6Random(N:Word):Word;πVarπ junk : Word;π myrandseed : Recordπ lo, hi : Wordπ end Absolute system.randseed;πbeginπ junk := Random(0); { Update Randseed }π TP6Random := myrandseed.hi mod N;πend;ππ{πYou might want to keep the following around in Case the update algorithm getsπchanged sometime in the future:ππDemonstration Program to show how the TP 6.0 random number generatorπupdates System.Randseed. Allows the seed to be cycled backwards. }ππProcedure CycleRandseed(cycles:Integer);π{ For cycles > 0, mimics cycles calls to the TP random number generator.π For cycles < 0, backs it up the given number of calls. }πVarπ i : Integer;πbeginπ if cycles > 0 thenπ For i := 1 to cycles doπ system.randseed := system.randseed*134775813 + 1π elseπ For i := -1 downto cycles doπ system.randseed := (system.randseed-1)*(-649090867);πend;ππVarπ i : Integer;πbeginπ randomize;π Writeln('Forwards:');π For i:=1 to 5 doπ Writeln(random);π Writeln('Backwards:');π For i:=1 to 5 doπ beginπ CycleRandseed(-1); { Back to previous value }π Writeln(random); { Show it }π CycleRandseed(-1); { Back up over it again }π end;πend.π 17 05-28-9313:53ALL SWAG SUPPORT TEAM REALFRMT.PAS IMPORT 8 ₧8╕▓ {π I recently came across the need For a way to dynamically Formatπ Real Variables For output - I came out With the following. (Youπ people following the Compiler thread may want this to make yourπ Compiler output pretty)ππ The routine checks to see how big the exponent is; if it's biggerπ than 1E7 or smaller than 1E-7, an unFormatted conversion is made.π if the number is less than 1E7 and greater than 1E-7, then aπ Formatted String is created. to make the output prettier, trailingπ zeros, periods and leading spaces are deleted.π}ππFunction FormatReal(r:Real):String;πVarπ s :String;ππbeginπ if ((r>1E-7) and (r<1E7))thenπ Str(r:12:12, s)π elseπ Str(r, s);ππ While s[ord(s[0])]='0' doπ Delete(s, ord(s[0]), 1);π While (s[1]=' ') doπ Delete(s, 1, 1);π if s[ord(s[0])]='.' thenπ Delete(s, ord(s[0]), 1);ππ FormatReal := s;πend;π 18 05-28-9313:53ALL SWAG SUPPORT TEAM REVERSE.PAS IMPORT 7 ₧8▓á {π a problem. I am asked to find the reverse of a positive Integer. Forπ example the reverse of 123 is 321 or the reverse of 1331 is 1331.π My teacher said that we should use div and MOD.π}ππVarπ X, Y: Integer;ππbeginπ X := PositiveInteger;π Y := 0;ππ While X > 0 doπ beginπ Y := (Y * 10) + (X mod 10);π X := X div 10;π end;ππ{πThe result will be in Y. Just so you do learn something of use out of this: Itπis a fact that the difference between two transposed (reversed) numbers will beπevenly divisible by 9. This can be of help if you are doing somethingπaccounting related and are trying to figure out why your numbers don't jive. ifπthe amount you are out is evenly divisible by 9, it is most likely aπtransposing error.π}π 19 05-28-9313:53ALL SWAG SUPPORT TEAM ROMAN1.PAS IMPORT 19 ₧8Z {π· Subject: Word to Roman Numeralππ OK, here is my second attempt, With error checking and all. Thanks toπTerry Moore <T.Moore@massey.ac.nz> For encouraging me. The last Functionπalso contained a couple of errors. This one is errorchecked.π}ππFunction RomantoArabic(Roman : String) : Integer;π{ Converts a Roman number to its Integer representation }π{ Returns -1 if anything is wrong }ππ Function Valueof(ch : Char) : Integer;π beginπ Case ch ofπ 'I' : Valueof:=1;π 'V' : Valueof:=5;π 'X' : Valueof:=10;π 'L' : Valueof:=50;π 'C' : Valueof:=100;π 'D' : Valueof:=500;π 'M' : Valueof:=1000;π else Valueof:=-1;π end;π end; { Valueof }ππ Function AFive(ch : Char) : Boolean; { Returns True if ch = 5,50,500 }π beginπ AFive:=ch in ['V','L','D'];π end; { AFive }ππVarπ Position : Byte;π TheValue, CurrentValue : Integer;π HighestPreviousValue : Integer;πbeginπ Position:=Length(Roman); { Initialize all Variables }π TheValue:=0;π HighestPreviousValue:=Valueof(Roman [Position]);π While Position > 0 doπ beginπ CurrentValue:=Valueof(Roman [Position]);π if CurrentValue<0 thenπ beginπ RomantoArabic:=-1;π Exit;π end;π if CurrentValue >= HighestPreviousValue thenπ beginπ TheValue:=TheValue+CurrentValue;π HighestPreviousValue:=CurrentValue;π endπ elseπ begin { if the digit precedes something larger }π if AFive(Roman [Position]) thenπ beginπ RomantoArabic:=-1; { A five digit can't precede anything }π Exit;π end;π if HighestPreviousValue div CurrentValue > 10 thenπ beginπ RomantoArabic:=-1; { e.g. 'XM', 'IC', 'XD'... }π Exit;π end;π TheValue:=TheValue-CurrentValue;π end;π Dec(Position);π end;π RomantoArabic:=TheValue;πend; { RomantoArabic }ππbeginπ Writeln('XXIV = ', RomantoArabic('XXIV'));π Writeln('DXIV = ', RomantoArabic('DXIV'));π Writeln('CXIV = ', RomantoArabic('CXIV'));π Writeln('MIXC = ', RomantoArabic('MIXC'));π Writeln('MXCIX = ', RomantoArabic('MXCIX'));π Writeln('LXVIII = ', RomantoArabic('LXVIII'));π Writeln('MCCXXIV = ', RomantoArabic('MCCXXIV'));π Writeln('MMCXLVI = ', RomantoArabic('MMCXLVI'));π Readln;πend. 20 05-28-9313:53ALL SWAG SUPPORT TEAM ROMAN2.PAS IMPORT 10 ₧8ß {π>Anyone know of how to make a Program that will convert anyπ>Integer entered into roman numeral Format?π}ππProgram Roman_Numeral_Test;ππTypeπ st_4 = String[4];π st_15 = String[15];π star_4 = Array[0..3] of st_4;π star_10 = Array[0..9] of st_4;ππConstπ Wunz : star_10 = ('', 'I', 'II', 'III', 'IV',π 'V', 'VI', 'VII', 'VIII', 'IX');ππ Tenz : star_10 = ('', 'X', 'XX', 'XXX', 'XL',π 'L', 'LX', 'LXX', 'LXXX', 'XC');ππ Hunz : star_10 = ('', 'C', 'CC', 'CCC', 'CD',π 'D', 'DC', 'DCC', 'DCCC', 'CM');ππ Thouz : star_4 = ('', 'M', 'MM', 'MMM');πππFunction Dec2Roman(wo_in : Word) : st_15;πbeginπ Dec2Roman := Thouz[(wo_in div 1000)] +π Hunz[((wo_in mod 1000) div 100)] +π Tenz[(((wo_in mod 1000) mod 100) div 10)] +π Wunz[(((wo_in mod 1000) mod 100) mod 10)]πend;ππVarπ wo_Temp : Word;ππbeginπ Writeln;π Write(' Enter number to be converted to roman-numeral equivalent: ');π readln(wo_Temp);π if (wo_Temp > 3999) thenπ wo_Temp := 3999;π Writeln;π Writeln(' Roman-numeral equivalent of ', wo_Temp, ' = ', Dec2Roman(wo_Temp))πend.ππ 21 05-28-9313:53ALL SWAG SUPPORT TEAM SHLSHR.PAS IMPORT 24 ₧85M { INFO ON SHR and SHL }ππ> (5 Shl 2) + 5 which is: (5 x 4) + 5π> So, 10 * 10 would be (10 Shl 3) + (10 Shl 1)ππThis looks good but, can it be done With Variables (So I can useπnumbers other than 5 & 5)?ππ Yes, just keep in mind that each shift leftward Doubles the value...ππ p SHL 1 = p * 2π p SHL 2 = p * 4π p SHL 3 = p * 8π p SHL 4 = p * 16π ...ππ (likewise, each shift rightward halves the value).ππ Also keep in mind that the maximum amount you can shift is theπ number of bits in the Variable. Bytes are 8 bits, Words andπ Integers are 16 bits, and LongInts are 32 bits. if you shiftπ a Variable its full bit size, or more, it will be 0 (zero).ππ For example: if p is a Byte, then p SHR 8 = 0.ππ{ Use Shr/Shl to multiply/divide, rather than the operatorsπ How do you (or anybody) do this? For example, how would I do 5 * 5?π}π{*******************************************************************}π Program DemoShifts;π Var Number, Result : Word;π beginπ { Calculate 5 * 5, without using multiplication ... }ππ Number := 5; { original value }π Result := Number SHL 2; { now Result = 4 * Number }π Result := Result + Number; { 4*Number + Number = 5*Number }ππ WriteLn( '5 * 5 = ', Result ); { because seeing is believing }ππ end {DemoShifts}.π{*******************************************************************}ππ But TP seems sometimes to do the 'shift vs. MUL optimization' itself,π this being bad if Compiling For a 386/486 CPU.π A "* 2" would always result in a SHL instruction ( unless Realπ arithmetic was used ;-> ).ππ Ok, I understand that part. if x shr 4 = x/4 (and the remainder isπ dropped) then I Really understand it. Does it? Do I?ππNo. x shl 0 = xπ x shl 1 = x/(2^1) = x/2π x shl 2 = x/(2^2) = x/4π x shl 3 = x/(2^3) = x/8π x shl 4 = x/(2^4) = x/16ππJust as:π x shr 0 = xπ x shr 1 = x*(2^1) = 2xπ x shr 2 = x*(2^2) = 4xπ x shr 3 = x*(2^3) = 8xπ x shr 4 = x*(2^4) = 16xππSo now you can see how and why the Compiler substitutes a "shr 1" For "* 2".ππ > PD> So, 10 * 10 would be: (10 shl 3) + 20π >π > MC> not quite:π > MC> (10 Shl 3)+(10 Shl 1)s, I'm back! (3:634/384.6)π >π > Why? wouldn't the second one take an additional instruction (shl)?ππWell yes, but 8086 instructions weren't created equal. PerForming twoπshifts and the add to combine them will (on a 286 or lesser) less timeπoverall than doing even one MUL.ππThe 386/486 has streamlined the MUL instruction so that it takes much lessπtime, and can often Compete With the shift/add approach. Which to use?πWell, I'd stick With the shift/add approach, since if you're writing oneπProgram For both XTs and 386s, the XT will be acceptable, and so will theπ386. Using the MUL; True, 386 perFormance will be better, but your XTπperFormance will suffer quite a bit.π 22 05-28-9313:53ALL SWAG SUPPORT TEAM SWAPNUMS.PAS IMPORT 5 ₧8Bë {π>Is there a way (using bit manipulations such as AND, OR, XOR) toπ>swap to Variables without making a 3rd temporary Variable?π>ππIf the two Variables are numbers, and the following operationsπwon't overflow the limitations of the Type, then yes, you canπdo it like this:π}πVarπ A, B : Integer;ππbeginπ A := 5;π B := 3;ππ A := A + B;π B := A - B;π A := A - B;ππ { which isππ A := 5 + 3 (8)π B := 8 - 3 (5)π A := 8 - 5 (3)ππ A = 3π B = 5 }ππend; 23 05-28-9313:53ALL SWAG SUPPORT TEAM TP6RAND.PAS IMPORT 12 ₧8└ {πBorland changed the Random() algorithm between TP6 and TP/BP7. The Unitπbelow provides the TP6 Random Function in its Integer flavour. (TheπRandomize Procedure wasn't changed.)ππ{ * Turbo Pascal Runtime Library Version 6.0 * ;π * Random Number Generator * ;π * * ;π * Copyright (C) 1988,92 Borland International * }ππUnit TP6Rand;ππInterfaceππFunction Random(Max: Integer): Integer;ππImplementationππConstπ { Scaling Constant}π ConstM31 = LongInt(-31);π { Multiplication factor}π Factor: Word = $8405;πππFunction NextRand: LongInt; Assembler;π{π Compute next random numberπ New := 8088405H * Old + 1π Out DX:AX = Next random numberπ}πAsmπ MOV AX,RandSeed.Word[0]π MOV BX,RandSeed.Word[2]π MOV CX,AXπ MUL Factor.Word[0] { New = Old.w0 * 8405H }π SHL CX,1 { New.w2 += Old.w0 * 808H }π SHL CX,1π SHL CX,1π ADD CH,CLπ ADD DX,CXπ ADD DX,BX { New.w2 += Old.w2 * 8405H }π SHL BX,1π SHL BX,1π ADD DX,BXπ ADD DH,BLπ MOV CL,5π SHL BX,CLπ ADD DH,BLπ ADD AX,1 { New += 1 }π ADC DX,0π MOV RandSeed.Word[0],AXπ MOV RandSeed.Word[2],DXπend;ππFunction Random(Max: Integer): Integer; Assembler;πAsmπ CALL NextRandπ xor AX,AXπ MOV BX,Max.Word[0]π or BX,BXπ JE @@1π XCHG AX,DXπ div BXπ XCHG AX,DXπ@@1:πend;ππend.π 24 05-28-9313:53ALL SWAG SUPPORT TEAM WORD2HEX.PAS IMPORT 67 ₧8è╘ {π> 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.π} 25 08-27-9320:03ALL SEAN PALMER Handling Numbers in ASM IMPORT 9 ₧8H { SEAN PALMERππI've been playing around with the AAM instruction and came up with someπthings you guys might find useful...ππStrings as function results are WIERD with the inline Assembler. 8)π}ππfunction div10(b : byte) : byte; assembler;πasmπ mov al, bπ aamπ mov al, ahπend;ππfunction mod10(b : byte) : byte; assembler;πasmπ mov al, bπ aamπend;ππtypeπ str2 = string[2];π str8 = string[8];ππfunction toStr2(b : byte) : str2; assembler;πasm {only call with b=0~99}π les di, @RESULTπ cldπ mov al, 2π stosbπ mov al, bπ aamπ xchg ah, alπ add ax, $3030π stoswπend;ππ{makes date string in MM/DD/YY format from m,d,y}πfunction toDateStr(m,d,y:byte):str8;assembler;asm {only call with m,d,y=0~99}π les di, @RESULTπ cldπ mov al, 8π stosbπ mov al, mπ aamπ xchg ah, alπ add ax, $3030π stoswπ mov al, '/'π stosbπ mov al, dπ aamπ xchg ah, alπ add ax, $3030π stoswπ mov al, '/'π stosbπ mov al, yπ aamπ xchg ah, alπ add ax, $3030π stoswπend;πππ 26 08-27-9321:39ALL TREVOR CARLSON MS to IEEE Numbers IMPORT 9 ₧8 {πTrevor Carlsonππ> Does anyone have source examples of how to convert an MSBIN to aπ> LongInt Type Variable?π}ππTypeπ MKS = Array [0..3] of Byte;ππFunction MStoIEEE(Var MS) : Real;π{ Converts a 4 Byte Microsoft format single precision Real Variable asπ used in earlier versions of QuickBASIC and GW-BASIC to IEEE 6 Byte Real }πVarπ m : MKS Absolute MS;π r : Real;π ieee : Array [0..5] of Byte Absolute r;πbeginπ FillChar(r, sizeof(r), 0);π ieee[0] := m[3];π ieee[3] := m[0];π ieee[4] := m[1];π ieee[5] := m[2];π MStoieee := r;πend; { MStoIEEE }πππFunction IEEEtoMS(ie : Real) : LongInt;π{ LongInt Type used only For convenience of Typecasting. Note that this willπ only be effective where the accuracy required can be obtained in the 23π bits that are available With the MKS Type. }πVarπ ms : MKS;π ieee : Array [0..5] of Byte Absolute ie;πbeginπ ms[3] := ieee[0];π ms[0] := ieee[3];π ms[1] := ieee[4];π ms[2] := ieee[5];π IEEEtoMS := LongInt(ms);πend; { IEEEtoMS }π 27 08-27-9321:41ALL LOU DUCHEZ Convert number Base IMPORT 22 ₧8 {πLOU DUCHEZππ>does andbody know an easy way to convert a Byte value from it's Integerπ> notation to hex notatation?ππWell, thank you For this message. It finally got me off my keister (sp?) toπWrite a "decimal-to-hex" converter -- a project I'd been meaning to do, butπnever got around to. (Technically, since I was in a seated position, Iπremained on my keister the whole time, but you know what I mean). Actually,πthe following is not just "decimal-to-hex" -- it's decimal-to-any-base-from-π2-to-36-converter (because base 1 and below doesn't make sense, and afterπbase 36 I run out of alphabet to represent "digits"). Here is NUBASE:π}πππFunction nubase(numin : LongInt; base, numplaces : Byte) : String;πVarπ tmpstr : String;π remainder : Byte;π negatize : Boolean;πbeginπ negatize := (numin < 0); { Record if it's a negative number }π if negatize thenπ numin := abs(numin); { convert to positive For calcs }π tmpstr[0] := Char(numplaces); { set length of the output String }ππ While numplaces > 0 doπ begin { Loop: fills each space in String }π remainder := numin mod base; { get next "digit" (under new base) }π if remainder > 9 thenπ tmpstr[numplaces] := Char(remainder + 64 - 9) { convert to letter }π elseπ tmpstr[numplaces] := Char(remainder + 48); { use number as is }π numin := numin div base; { reduce dividend For next "pass" }π numplaces := numplaces - 1; { go to "next" position in String }π end; { end of loop }ππ { The following: if we've run out of room on the String, or if it's aπ negative number and there's not enough space For the "minus" sign,π convert the output String to all asterisks. }ππ if (numin <> 0) or (negatize and (tmpstr[1] <> '0')) thenπ For numplaces := 1 to Byte(tmpstr[0]) doπ tmpstr[numplaces] := '*';ππ { add minus sign }ππ if negatize and (tmpstr[1] = '0') thenπ tmpstr[1] := '-';ππ nubase := tmpstr;πend;πππ{πFeed it the number to convert, the base to convert into, and the number ofπspaces you want For it. Leading zeros will be provided. Example: toπconvert 111 into hex (base 16) and give 4 digits of answer, you could say:ππWriteln(nubase(111, 16, 4))ππand it'd Write out:ππ006FππThis routine does handle negative numbers too. if you don't give it enoughπ"space" in the third parameter you pass, it'll return all asterisks. Forπlaughs, try converting the number 111 into base 10 and giving it 5 digitsπof answer. You'll get:ππ00111 (predictably enough)π} 28 11-02-9305:00ALL CHRIS QUARTETTI Setting/Getting BITS SWAG9311 21 ₧8 {πCHRIS QUARTETTIππ>Is there an easy way to create a 1-bit or 2-bit data structure. Forπ>example, a 2-bit Type that can hold 4 possible values. For that matter,π>is there a hard way? <g> Thanks very much -Gregππ I suppose this would qualify For the hard way-- not too flexible, but itπworks. It would be a bit easier to do this if you wanted a bunch of the sameπsize Variables (ie 4 4 bit Variables, or an Array of 4*x 4 bit Variables).πFWIW I used BP7 here, but TP6 and up will work. Also, it need not be Objectπoriented.π}ππTypeπ bitf = Object { split 'bits' into bitfields }π bits : Word; { 16 bits total }ππ Function get : Word;ππ Procedure set1(value : Word); { this will be 2 bits }π Function get1 : Word;ππ Procedure set2(value : Word); { this will be 13 bits }π Function get2 : Word;ππ Procedure set3(value : Word); { this will be 1 bit }π Function get3 : Word;π end;ππFunction bitf.get : Word;πbeginπ get := bits;πend;ππProcedure bitf.set1(value : Word);π{ Set the value of the first bitfield }πConstπ valmask : Word = $C000; { 11000000 00000000 }π bitsmask : Word = $3FFF; { 00111111 11111111 }πbeginπ value := value shl 14 and valmask;π bits := value + (bits and bitsmask);πend;ππFunction bitf.get1 : Word;π{ Get the value of the first bitfield }πbeginπ get1 := bits shr 14;πend;ππProcedure bitf.set2(value : Word);π{ Set the value of the second bitfield }πConstπ valmask : Word = $3FFE; { 00111111 11111110 }π bitsmask : Word = $C001; { 11000000 00000001 }πbeginπ value := (value shl 1) and valmask;π bits := value + (bits and bitsmask);πend;ππFunction bitf.get2 : Word;π{ Get the value of the second bitfield }πConstπ valmask : Word = $3FFE; { 00111111 11111110 }πbeginπ get2 := (bits and valmask) shr 1;πend;ππProcedure bitf.set3(value : Word);π{ Set the value of the third bitfield }πConstπ valmask : Word = $0001; { 00000000 00000001 }π bitsmask : Word = $FFFE; { 11111111 11111110 }πbeginπ value := value and valmask;π bits := value + (bits and bitsmask);πend;ππFunction bitf.get3 : Word;π{ Get the value of the third bitfield }πConstπ valmask : Word = $0001; { 00000000 00000001 }πbeginπ get3 := bits and valmask;πend;ππVarπ x : bitf;ππbeginπ x.set1(3); { set all to maximum values }π x.set2(8191);π x.set3(1);π Writeln(x.get1, ', ', x.get2, ', ', x.get3, ', ', x.get);πend.π 29 11-21-9309:24ALL GREG VIGNEAULT Base Notation SWAG9311 21 ₧8 π{ How about a procedure that will display any integer in any baseπ notation from 2 to 16? The following example displays the valuesπ 0 through 15 in binary (base 2), octal (base 8), decimal (base 10)π and hexadecimal (base 16) notations ... }ππ(********************************************************************)πPROGRAM BaseX; (* compiler: Turbo Pascal v4.0+ *)π (* Nov.14.93 Greg Vigneault *)π(*------------------------------------------------------------------*)π(* Display any INTEGER in any base notation from 2 to 16... *)π(* *)π(* number base 2 = binary notation (digits 0,1) *)π(* number base 8 = octal notation (digits 0..7) *)π(* number base 10 = decimal notation (digits 0..9) *)π(* number base 16 = hexadecimal notation (digits 0..9,A..F) *)ππPROCEDURE DisplayInteger (AnyInteger :INTEGER; NumberBase :BYTE);π CONST DataSize = 16; (* bit-size of an INTEGER *)π VAR Index : INTEGER;π Digit : ARRAY [1..DataSize] OF CHAR;π BEGINπ IF (NumberBase > 1) AND (NumberBase < 17) THEN BEGINπ Index := 0;π REPEATπ INC (Index);π Digit [Index] := CHR(AnyInteger MOD NumberBase + ORD('0'));π IF (Digit [Index] > '9') THEN INC (Digit [Index],7);π AnyInteger := AnyInteger DIV NumberBase;π UNTIL (AnyInteger = 0) OR (Index = DataSize);π WHILE (Index > 0) DO BEGINπ Write (Digit [Index]);π DEC (Index);π END; {WHILE Index}π END; {IF NumberBase}π END {DisplayInteger};ππ(*------------------------------------------------------------------*)π(* to test the DisplayInteger procedure... *)ππVAR Base, Number : INTEGER;ππBEGINπ FOR Base := 2 TO 16 DOπ CASE Base OFπ 2,8,10,16 : BEGINπ WriteLn;π CASE Base OFπ 2 : Write ('Binary : ');π 8 : Write ('Octal : ');π 10 : Write ('Decimal: ');π 16 : Write ('Hex : ');π END; {CASE}π FOR Number := 0 TO 15 DO BEGINπ DisplayInteger (Number, Base);π Write (' ');π END; {FOR}π END;π END; {CASE}π WriteLn;ππEND {BaseX}.π 30 11-02-9305:52ALL GREG VIGNEAULT LongInt to HEX SWAG9311 11 ₧8 {πGREG VIGNEAULTππ> So to assign the File I will need the HEX in String format.π}ππTypeπ String8 = String[8];ππVarπ MyStr : String8;π ALong : LongInt;ππ{ convert a LongInt value to an 8-Character String, using hex digits }π{ (using all 8 Chars will allow correct order in a sorted directory) }ππProcedure LongToHex(AnyLong : LongInt; Var HexString : String8);πVarπ ch : Char;π Index : Byte;πbeginπ HexString := '00000000'; { default to zero }π Index := Length(HexString); { String length }π While AnyLong <> 0 doπ begin { loop 'til done }π ch := Chr(48 + Byte(AnyLong) and $0F); { 0..9 -> '0'..'9' }π if ch > '9' thenπ Inc(ch, 7); { 10..15 -> 'A'..'F'}π HexString[Index] := ch; { insert Char }π Dec(Index); { adjust chr Index }π AnyLong := AnyLong SHR 4; { For next nibble }π end;πend;ππbeginπ ALong := $12345678; { a LongInt value }π LongToHex(ALong, MyStr); { convert to hex str}π WriteLn;π WriteLn('$', MyStr); { display the String}π WriteLn;πend.π 31 10-28-9311:32ALL GREG VIGNEAULT Verify ISBN Numbers SWAG9311 17 ₧8 {===========================================================================πDate: 09-22-93 (20:14)πFrom: GREG VIGNEAULTπSubj: Pascal ISBN verificationππ Here's a snippet of TP code for the free SWAG archives. It verifiesπ ISBN numbers, via the embedded checksum ... }ππ(********************************************************************)π(* Turbo/Quick/StonyBrook Pascal source file: ISBN.PAS v1.0 GSV *)π(* Verify any International Standard Book Number (ISBN) ... *)ππPROGRAM checkISBN;ππCONST TAB = #9; { ASCII horizontal tab }π LF = #10; { ASCII line feed }ππVAR ISBNstr : STRING[16];π loopc, ISBNlen, M, chksm : BYTE;ππBEGIN {checkISBN}ππ WriteLn (LF,TAB,'ISBN Check v1.0 Copyright 1993 Greg Vigneault',LF);ππ IF ( ParamCount <> 1 ) THEN BEGIN { we want just one input parm }π WriteLn ( TAB, 'Usage: ISBN <ISBN#>', LF );π Halt(1);π END; {IF}ππ ISBNstr := ParamStr (1); { get the ISBN number }π Write ( TAB, 'Checking ISBN# ', ISBNstr, ' ...' );π { eliminate any non-digit characters from the ISBN string... }π ISBNlen := 0;π FOR loopc := 1 TO ORD ( ISBNstr[0] ) DOπ IF ( ISBNstr[ loopc ] IN ['0'..'9'] ) THEN BEGINπ INC ( ISBNlen );π ISBNstr[ ISBNlen ] := ISBNstr[ loopc ];π END; {IF & FOR}π { an 'X' at the end of the ISBN affects the result... }π IF ( ISBNstr[ ORD ( ISBNstr[0] ) ] IN ['X','x'] ) THENπ M := 10π ELSEπ M := ORD ( ISBNstr[ ISBNlen ] ) - 48;π ISBNstr[0] := CHR ( ISBNlen ); { new ISBN string length }π WriteLn ( 'reduced ISBN = ', ISBNstr ); WriteLn;π chksm := 0; { initialize checksum }π FOR loopc := 1 TO ISBNlen-1 DOπ INC (chksm, ( ORD ( ISBNstr[ loopc ] ) - 48 ) * loopc );π Write ( TAB, 'ISBN ' );π IF ( ( chksm MOD 11 ) = M ) THENπ WriteLn ( 'is okay.' )π ELSEπ WriteLn ( 'error!',#7 );ππEND {checkISBN}. (* Not for commercial retail. *)π 32 10-28-9311:31ALL J.P. RITCHEY MSBIN to IEEE SWAG9311 70 ₧8 {===========================================================================πDate: 10-09-93 (23:23)πFrom: J.P. RitcheyπSubj: MSBIN to IEEEπ---------------------------------------------------------------------------πGE> Does anyone have any code for Converting MSBIN formatπGE> numbers into IEEE? }ππ{$A-,B-,D-,E+,F-,I-,L-,N+,O-,R-,S-,V-}πunit BFLOAT;π(*π MicroSoft Binary Float to IEEE format Conversionπ Copyright (c) 1989 J.P. Ritcheyπ Version 1.0ππ This software is released to the public domain. Thoughπ tested, there could be some errors. Any reports of bugsπ discovered would be appreciated. Send reports toπ Pat Ritchey Compuserve ID 72537,2420π*)πinterfaceππtypeπ bfloat4 = recordπ { M'Soft single precision }π mantissa : array[5..7] of byte;π exponent : byte;π end;ππ Bfloat8 = recordπ { M'Soft double precision }π mantissa : array[1..7] of byte;π exponent : byte;π end;πππFunction Bfloat4toExtended(d : bfloat4) : extended;πFunction Bfloat8toExtended(d : Bfloat8): extended;ππ{ These routines will convert a MicroSoft Binary Floating pointπ number to IEEE extended format. The extended is large enoughπ to store any M'Soft single or double number, so no over/underflowπ problems are encountered. The Mantissa of an extended is large enoughπ to hold a BFloatx mantissa, so no truncation is required.ππ The result can be returned to TP single and double variables andπ TP will handle the conversion. Note that Over/Underflow can occurπ with these types. }ππFunction HexExt(ep:extended) : string;ππ{ A routine to return the hex representation of an IEEE extended variableπ Left in from debugging, you may find it useful }ππFunction ExtendedtoBfloat4(ep : extended; var b : bfloat4) : boolean;πFunction ExtendedtoBfloat8(ep : extended; var b : Bfloat8) : boolean;ππ{ These routines are the reverse of the above, that is they convertπ TP extended => M'Soft format. You can use TP singles and doublesπ as the first parameter and TP will do the conversion to extendedπ for you.ππ The Function result returns True if the conversion was succesful,π and False if not (because of overflow).ππ Since an extended can have an exponent that will not fitπ in the M'Soft format Over/Underflow is handled in the followingπ manner:π Overflow: Set the Bfloatx to 0 and return a False result.π Underflow: Set the BFloatx to 0 and return a True Result.ππ No rounding is done on the mantissa. It is simply truncated toπ fit. }πππFunction BFloat4toReal(b:bfloat4) : Real;πFunction BFloat8toReal(b:bfloat8) : Real;ππ{ These routines will convert a MicroSoft Binary Floating pointπ number to Turbo real format. The real is large enoughπ to store any M'Soft single or double Exponent, so no over/underflowπ problems are encountered. The Mantissa of an real is large enoughπ to hold a BFloat4 mantissa, so no truncation is required. Theπ BFloat8 mantissa is truncated (from 7 bytes to 5 bytes) }ππFunction RealtoBFloat4(rp: real; var b:bfloat4) : Boolean;πFunction RealtoBFloat8(rp : real; var b:bfloat8) : Boolean;ππ{ These routines do the reverse of the above. No Over/Underflow canπ occur, but truncation of the mantissa can occurπ when converting Real to Bfloat4 (5 bytes to 3 bytes).ππ The function always returns True, and is structured this way toπ function similar to the IEEE formats }ππimplementationπtypeπ IEEEExtended = recordπ Case integer ofπ 0 : (Mantissa : array[0..7] of byte;π Exponent : word);π 1 : (e : extended);π end;ππ TurboReal = recordπ Case integer ofπ 0 : (Exponent : byte;π Mantissa : array[3..7] of byte);π 1 : (r : real);π end;ππFunction HexExt(ep:extended) : string;πvarπ e : IEEEExtended absolute ep;π i : integer;π s : string;π Function Hex(b:byte) : string;π const hc : array[0..15] of char = '0123456789ABCDEF';π beginπ Hex := hc[b shr 4]+hc[b and 15];π end;πbeginπ s := hex(hi(e.exponent))+hex(lo(e.exponent))+' ';π for i := 7 downto 0 do s := s+hex(e.mantissa[i]);πHexExt := s;πend;ππFunction NullMantissa(e : IEEEextended) : boolean;πvarπ i : integer;πbeginπNullMantissa := False;πfor i := 0 to 7 do if e.mantissa[i] <> 0 then exit;πNullMantissa := true;πend;ππProcedure ShiftLeftMantissa(var e);π{ A routine to shift the 8 byte mantissa left one bit }πinline(π{0101} $F8/ { CLC }π{0102} $5F/ { POP DI }π{0103} $07/ { POP ES }π{0104} $B9/$04/$00/ { MOV CX,0004 }π{0107} $26/$D1/$15/ { RCL Word Ptr ES:[DI],1 }π{010A} $47/ { INC DI }π{010B} $47/ { INC DI }π{010C} $E2/$F9 { LOOP 0107 }π);ππProcedure Normalize(var e : IEEEextended);π{ Normalize takes an extended and insures that the "i" bit isπ set to 1 since M'Soft assumes a 1 is there. An extended hasπ a value of 0.0 if the mantissa is zero, so the first check.π The exponent also has to be kept from wrapping from 0 to $FFFFπ so the "if e.exponent = 0" check. If it gets this smallπ for the routines that call it, there would be underflow and 0π would be returned.π}πvarπ exp : word;ππbeginπexp := e.exponent and $7FFF; { mask out sign }πif NullMantissa(e) thenπ beginπ E.exponent := 0;π exitπ end;πwhile e.mantissa[7] < 128 doπ beginπ ShiftLeftMantissa(e);π dec(exp);π if exp = 0 then exit;π end;πe.exponent := (e.exponent and $8000) or exp; { restore sign }πend;ππFunction Bfloat8toExtended(d : Bfloat8) : extended;πvarπ i : integer;π e : IEEEExtended;πbeginπ fillchar(e,sizeof(e),0);π Bfloat8toExtended := 0.0;π if d.exponent = 0 then exit;π { if the bfloat exponent is 0 the mantissa is ignored andπ the value reurned is 0.0 }π e.exponent := d.exponent - 129 + 16383;π { bfloat is biased by 129, extended by 16383π This creates the correct exponent }π if d.mantissa[7] > 127 thenπ { if the sign bit in bfloat is 1 then set the sign bit in the extended }π e.exponent := e.exponent or $8000;π move(d.Mantissa[1],e.mantissa[1],6);π e.mantissa[7] := $80 or (d.mantissa[7] and $7F);π { bfloat assumes 1.fffffff, so supply it for extended }π Bfloat8toExtended := e.e;πend;ππFunction Bfloat4toExtended(d : bfloat4) : extended;πvarπ i : integer;π e : IEEEExtended;πbeginπ fillchar(e,sizeof(e),0);π Bfloat4toExtended := 0.0;π if d.exponent = 0 then exit;π e.exponent := integer(d.exponent - 129) + 16383;π if d.mantissa[7] > 127 thenπ e.exponent := e.exponent or $8000;π move(d.Mantissa[5],e.mantissa[5],2);π e.mantissa[7] := $80 or (d.mantissa[7] and $7F);π Bfloat4toExtended := e.e;πend;ππFunction ExtendedtoBfloat8(ep : extended; var b : Bfloat8) : boolean;πvarπ e : IEEEextended absolute ep;π exp : integer;π sign : byte;πbeginπFillChar(b,Sizeof(b),0);πExtendedtoBfloat8 := true; { assume success }πNormalize(e);πif e.exponent = 0 then exit;πsign := byte(e.exponent > 32767) shl 7;πexp := (e.exponent and $7FFF) - 16383 + 129;πif exp < 0 then exp := 0; { underflow }πif exp > 255 then { overflow }π beginπ ExtendedtoBfloat8 := false;π exit;π end;πb.exponent := exp;πmove(e.mantissa[1],b.mantissa[1],7);πb.mantissa[7] := (b.mantissa[7] and $7F) or sign;πend;ππFunction ExtendedtoBfloat4(ep : extended; var b : Bfloat4) : boolean;πvarπ e : IEEEextended absolute ep;π exp : integer;π sign : byte;πbeginπFillChar(b,Sizeof(b),0);πExtendedtoBfloat4 := true; { assume success }πNormalize(e);πif e.exponent = 0 then exit;πsign := byte(e.exponent > 32767) shl 7;πexp := (e.exponent and $7FFF) - 16383 + 129;πif exp < 0 then exp := 0; { underflow }πif exp > 255 then { overflow }π beginπ ExtendedtoBfloat4 := false;π exit;π end;πb.exponent := exp;πmove(e.mantissa[5],b.mantissa[5],3);πb.mantissa[7] := (b.mantissa[7] and $7F) or sign;πend;ππFunction BFloat4toReal(b:bfloat4) : Real;πvarπ r : TurboReal;πbeginπ fillchar(r,sizeof(r),0);π r.exponent := b.exponent;π move(b.mantissa[5],r.mantissa[5],3);π Bfloat4toReal := r.r;πend;ππFunction BFloat8toReal(b:bfloat8) : Real;πvarπ r : TurboReal;πbeginπ fillchar(r,sizeof(r),0);π r.exponent := b.exponent;π move(b.mantissa[3],r.mantissa[3],5);π Bfloat8toReal := r.r;πend;ππFunction RealtoBFloat4(rp: real; var b:bfloat4) : Boolean;πvarπ r : TurboReal absolute rp;πbeginπ fillchar(b,sizeof(b),0);π b.exponent := r.exponent;π move(r.mantissa[5],b.mantissa[5],3);π RealtoBfloat4 := true;πend;ππFunction RealtoBFloat8(rp : real; var b:bfloat8) : Boolean;πvarπ r : TurboReal absolute rp;πbeginπ fillchar(b,sizeof(b),0);π b.exponent := r.exponent;π move(r.mantissa[3],b.mantissa[3],5);π RealtoBfloat8 := true;πend;ππend.π 33 09-26-9310:53ALL KENT BRIGGS Random Number Generator SWAG9311 8 ₧8 (*πFrom: KENT BRIGGS Refer#: NONEπSubj: TP 7.0 RANDOM GENERATOR Conf: (1221) F-PASCALπ*)ππconstπ rseed: longint = 0;ππprocedure randomize67; {TP 6.0 & 7.0 seed generator}πbeginπ reg.ah:=$2c;π msdos(reg); {get time: ch=hour,cl=min,dh=sec,dl=sec/100}π rseed:=reg.dx;π rseed:=(rseed shl 16) or reg.cx;πend;ππfunction rand_word6(x: word): word; {TP 6.0 RNG: word}πbeginπ rseed:=rseed*134775813+1;π rand_word6:=(rseed shr 16) mod x;πend;ππfunction rand_word7(x: word): word; {TP 7.0 RNG: word}πbeginπ rseed:=rseed*134775813+1;π rand_word7:=((rseed shr 16)*x+((rseed and $ffff)*x shr 16)) shr 16;πend;ππfunction rand_real67: real; {TP 6.0 & 7.0 RNG: real}πbeginπ rseed:=rseed*134775813+1;π if rseed<0 then rand_real67:=rseed/4294967296.0+1.0 elseπ rand_real67:=rseed/4294967296.0;πend;π 34 09-26-9309:31ALL MARTIN RICHARDSON Get HIGH order of WORD SWAG9311 7 ₧8 {*****************************************************************************π * Function ...... wHi()π * Purpose ....... Return the High order word from a longint (double word)π * Parameters .... n LONGINT to retrieve high word fromπ * Returns ....... High word from nπ * Notes ......... HI only returns the HIgh byte from a word. I neededπ * something that returned the high WORD from a LONGINT.π * Author ........ Martin Richardsonπ * Date .......... October 9, 1992π *****************************************************************************}πFUNCTION wHi( n: LONGINT ): WORD; ASSEMBLER;πASMπ MOV AX, WORD PTR n[2]πEND;ππ 35 09-26-9309:31ALL MARTIN RICHARDSON Get Low Order of WORD SWAG9311 7 ₧8 {*****************************************************************************π * Function ...... wLo()π * Purpose ....... Return the low order word from a longint (double word)π * Parameters .... n LONGINT to retrieve low word fromπ * Returns ....... Low word from nπ * Notes ......... LO only returns the LOw byte from a word. I neededπ * something that returned the low WORD from a LONGINT.π * Author ........ Martin Richardsonπ * Date .......... October 9, 1992π *****************************************************************************}πFUNCTION wLo( n: LONGINT ): WORD; ASSEMBLER;πASMπ MOV AX, WORD PTR n[0]πEND;ππ 36 11-02-9305:01ALL ROBERT ROTHENBURG More Get/Set Bits SWAG9311 21 ₧8 {πRobert RothenburgππHere's some routines I wrote while playing around with some compressionπalgorithms. Since they're written in Pascal, they're probably not tooπfast but they work.πππOf course they're need some tweaking.π}π(* NoFrills Bit-Input/Output Routines *)π(* Insert "n" bits of data into a Buffer or Pull "n" bits of *)π(* data from a buffer. Useful for Compression routines *)πππunit BitIO;ππinterfaceππconstπ BufferSize = 32767; (* Adjust as appropriate *)ππtypeπ Buffer = array [0..BufferSize] of byte;π BufPtr = ^Buffer;π BuffRec = record (* This was used for I/O by some *)π Block : BufPtr; (* other units involved with the *)π Size, (* compression stuff. Not so *)π Ptr : word; (* Important? *)π Loc : byteπ end;ππvarπ InBuffer,π OutBuffer : BuffRec;π InFile,π OutFile : file;ππprocedure InitBuffer(var x : BuffRec); (* Initialize a buffer *)πprocedure GetBits(var b : word; num : byte); (* Get num bits from *)π (* InBuffer *)πprocedure PutBits(b : word; num : byte); (* Put num bits into *)π (* OutBuffer *)πfunction Log2(x : word) : byte; (* Self-explanatory... *)ππimplementationππconstπ Power : array [1..17] of longint =π (1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536);ππprocedure InitBuffer(var x : BuffRec);πbeginπ with x doπ beginπ Loc := 8;π Ptr := 0;π Size := 0;π New(Block);π FillChar(Block^, BufferSize, #0);π end;πend;ππprocedure GetBits(var b : word; num : byte);πvarπ Size : word;πbeginπ with InBuffer doπ beginπ b := 0;π repeatπ b := (b SHL 1);π if (Block^[Ptr] AND Power[Loc]) <> 0 thenπ b := b OR 1;π dec(Loc);π if Loc = 0 thenπ beginπ Loc := 8;π inc(Ptr);π end;π dec(num);π until (num = 0);π end;πend;ππprocedure PutBits(b : word; num : byte);πvarπ i : byte;πbeginπ with OutBuffer doπ repeatπ if Loc = 0 thenπ beginπ inc(Ptr);π Loc := 8;π end;π if (b AND Power[num]) <> 0 thenπ beginπ Block^[Ptr] := Block^[Ptr] OR Power[Loc];π dec(Loc);π endπ elseπ dec(Loc);π dec(num)π until num = 0;π OutBuffer.Size := succ(OutBuffer.Ptr);πend;ππfunction Log2(x : word) : byte;πvarπ i : byte;πbeginπ i := 17;π while x<Power[i] doπ dec(i);π Log2 := i;πend;ππend.π 37 11-21-9309:25ALL SWAG SUPPORT TEAM Bit Handler SWAG9311 44 ₧8 UNIT Bits;π(**) INTERFACE (**)πTYPEπ bbit = 0..7;π wbit = 0..15;π lbit = 0..31;ππ PROCEDURE SetBitB(VAR B : Byte; bit : bbit);π PROCEDURE ClearBitB(VAR B : Byte; bit : bbit);π PROCEDURE ToggleBitB(VAR B : Byte; bit : bbit);π FUNCTION BitSetB(B : Byte; bit : bbit) : Boolean;π FUNCTION BitClearB(B : Byte; bit : bbit) : Boolean;ππ PROCEDURE SetBitW(VAR W : Word; bit : wbit);π PROCEDURE ClearBitW(VAR W : Word; bit : wbit);π PROCEDURE ToggleBitW(VAR W : Word; bit : wbit);π FUNCTION BitSetW(W : Word; bit : wbit) : Boolean;π FUNCTION BitClearW(W : Word; bit : wbit) : Boolean;ππ PROCEDURE SetBitL(VAR L : LongInt; bit : lbit);π PROCEDURE ClearBitL(VAR L : LongInt; bit : lbit);π PROCEDURE ToggleBitL(VAR L : LongInt; bit : lbit);π FUNCTION BitSetL(L : LongInt; bit : lbit) : Boolean;π FUNCTION BitClearL(L : LongInt; bit : lbit) : Boolean;ππ(**) IMPLEMENTATION (**)π PROCEDURE SetBitB(VAR B : Byte; bit : bbit);π Assembler;π ASMπ MOV CL, bitπ MOV BL, 1π SHL BL, CL {BL contains 2-to-the-bit}π LES DI, Bπ OR ES:[DI], BL {OR turns on bit}π END;ππ PROCEDURE ClearBitB(VAR B : Byte; bit : bbit);π Assembler;π ASMπ MOV CL, bitπ MOV BL, 1π SHL BL, CL {BL contains 2-to-the-bit}π NOT BLπ LES DI, Bπ AND ES:[DI], BL {AND of NOT BL turns off bit}π END;ππ PROCEDURE ToggleBitB(VAR B : Byte; bit : bbit);π Assembler;π ASMπ MOV CL, bitπ MOV BL, 1π SHL BL, CL {BL contains 2-to-the-bit}π LES DI, Bπ XOR ES:[DI], BL {XOR toggles bit}π END;ππ FUNCTION BitSetB(B : Byte; bit : bbit) : Boolean;π Assembler;π ASMπ MOV CL, bitπ MOV BL, 1π SHL BL, CL {BL contains 2-to-the-bit}π MOV AL, 0 {set result to FALSE}π TEST B, BLπ JZ @Noπ INC AL {set result to TRUE}π @No:π END;ππ FUNCTION BitClearB(B : Byte; bit : bbit) : Boolean;π Assembler;π ASMπ MOV CL, bitπ MOV BL, 1π SHL BL, CL {BL contains 2-to-the-bit}π MOV AL, 0 {set result to FALSE}π TEST B, BLπ JNZ @Noπ INC AL {set result to TRUE}π @No:π END;ππ PROCEDURE SetBitW(VAR W : Word; bit : wbit);π Assembler;π ASMπ MOV CL, bitπ MOV BX, 1π SHL BX, CL {BX contains 2-to-the-bit}π LES DI, Wπ OR ES:[DI], BX {OR turns on bit}π END;ππ PROCEDURE ClearBitW(VAR W : Word; bit : wbit);π Assembler;π ASMπ MOV CL, bitπ MOV BX, 1π SHL BX, CL {BX contains 2-to-the-bit}π NOT BXπ LES DI, Wπ AND ES:[DI], BX {AND of NOT BX turns off bit}π END;ππ PROCEDURE ToggleBitW(VAR W : Word; bit : wbit);π Assembler;π ASMπ MOV CL, bitπ MOV BX, 1π SHL BX, CL {BX contains 2-to-the-bit}π LES DI, Wπ XOR ES:[DI], BX {XOR toggles bit}π END;ππ FUNCTION BitSetW(W : Word; bit : wbit) : Boolean;π Assembler;π ASMπ MOV CL, bitπ MOV BX, 1π SHL BX, CL {BX contains 2-to-the-bit}π MOV AL, 0 {set result to FALSE}π TEST W, BXπ JZ @Noπ INC AL {set result to TRUE}π @No:π END;ππ FUNCTION BitClearW(W : Word; bit : wbit) : Boolean;π Assembler;π ASMπ MOV CL, bitπ MOV BX, 1π SHL BX, CL {BX contains 2-to-the-bit}π MOV AL, 0 {set result to FALSE}π TEST W, BXπ JNZ @Noπ INC AL {set result to TRUE}π @No:π END;ππ PROCEDURE SetBitL(VAR L : LongInt; bit : lbit);π Assembler;π ASMπ LES DI, Lπ MOV CL, bitπ MOV BX, 1π SHL BX, CL {BX contains 2-to-the-bit}π JZ @TopWord {if zero, use high word}π OR ES:[DI], BX {OR turns on bit}π JMP @Finishπ @TopWord:π SUB CL, 16π MOV BX, 1π SHL BX, CLπ OR ES:[DI+2], BXπ @Finish:π END;ππ PROCEDURE ClearBitL(VAR L : LongInt; bit : lbit);π Assembler;π ASMπ LES DI, Lπ MOV CL, bitπ MOV BX, 1π SHL BX, CL {BX contains 2-to-the-bit}π JZ @TopWord {if zero, use high word}π NOT BXπ AND ES:[DI], BX {AND of NOT BX turns off bit}π JMP @Finishπ @TopWord:π SUB CL, 16π MOV BX, 1π SHL BX, CLπ NOT BXπ AND ES:[DI+2], BXπ @Finish:π END;ππ PROCEDURE ToggleBitL(VAR L : LongInt; bit : lbit);π Assembler;π ASMπ LES DI, Lπ MOV CL, bitπ MOV BX, 1π SHL BX, CL {BX contains 2-to-the-bit}π JZ @TopWord {if zero, use high word}π XOR ES:[DI], BX {XOR toggles bit}π JMP @Finishπ @TopWord:π SUB CL, 16π MOV BX, 1π SHL BX, CLπ XOR ES:[DI+2], BXπ @Finish:π END;ππ FUNCTION BitSetL(L : LongInt; bit : lbit) : Boolean;π Assembler;π ASMπ MOV AL, 0 {set result to FALSE}π MOV CL, bitπ MOV BX, 1π SHL BX, CL {BX contains 2-to-the-bit}π JZ @TopWord {if zero, use high word}π TEST Word(L), BXπ JMP @Finishπ @TopWord:π SUB CL, 16π MOV BX, 1π SHL BX, CLπ TEST Word(L+2), BXπ @Finish:π JZ @Noπ INC AL {set result to TRUE}π @No:π END;ππ FUNCTION BitClearL(L : LongInt; bit : lbit) : Boolean;π Assembler;π ASMπ MOV AL, 0 {set result to FALSE}π MOV CL, bitπ MOV BX, 1π SHL BX, CL {BX contains 2-to-the-bit}π JZ @TopWord {if zero, use high word}π TEST Word(L), BXπ JMP @Finishπ @TopWord:π SUB CL, 16π MOV BX, 1π SHL BX, CLπ TEST Word(L+2), BXπ @Finish:π JNZ @Noπ INC AL {set result to TRUE}π @No:π END;πEND.π 38 11-21-9309:36ALL SWAG SUPPORT TEAM HILO Bit Operators SWAG9311 12 ₧8 UNIT HiLo;π(**) INTERFACE (**)π FUNCTION SwapN(B : Byte) : Byte;π FUNCTION HiN(B : Byte) : Byte;π FUNCTION LoN(B : Byte) : Byte;ππ FUNCTION SwapW(L : LongInt) : LongInt;π FUNCTION HiW(L : LongInt) : Word;π FUNCTION LoW(L : LongInt) : Word;ππ FUNCTION WordFromB(H, L : Byte) : Word;π FUNCTION LongFromW(H, L : Word) : LongInt;ππ(**) IMPLEMENTATION (**)π FUNCTION SwapN(B : Byte) : Byte; Assembler;π ASMπ MOV AL, B {byte in AL}π MOV AH, AL {now in AH too}π MOV CL, 4 {set up to shift by 4}π SHL AL, CL {AL has low nibble -> high}π SHR AH, CL {AH has high nibble -> low}π ADD AL, AH {combine them}π END;ππ FUNCTION HiN(B : Byte) : Byte; Assembler;π ASMπ MOV AL, Bπ MOV CL, 4π SHR AL, CLπ END;ππ FUNCTION LoN(B : Byte) : Byte; Assembler;π ASMπ MOV AL, Bπ AND AL, 0Fhπ END;ππ FUNCTION SwapW(L : LongInt) : LongInt; Assembler;π ASMπ MOV AX, Word(L+2)π MOV DX, Word(L)π END;ππ FUNCTION HiW(L : LongInt) : Word; Assembler;π ASMπ MOV AX, Word(L+2)π END;ππ FUNCTION LoW(L : LongInt) : Word; Assembler;π ASMπ MOV AX, Word(L);π END;ππ FUNCTION WordFromB(H, L : Byte) : Word; Assembler;π ASMπ MOV AH, Hπ MOV AL, Lπ END;ππ FUNCTION LongFromW(H, L : Word) : LongInt; Assembler;π ASMπ MOV DX, Hπ MOV AX, Lπ END;πEND. 39 01-27-9411:56ALL DJ MURDOCH Complex Numbers SWAG9402 11 ₧8 {π>A>overlooked. No Pascal compiler that I know of (including Turbo) can returnπ>A>a complex value (i.e., a record or an array) from a FUNCTION. In order forπ>π>Hmm...never tried this before. Anyway, the sollution is quite simple:π>just have the megaword-variable public, and pass it to the procedure.ππReturning function values by setting a public variable is pretty dangerous -πwhat if your function calls another that uses the same public to return itsπvalue? In this case, it's not necessary, since there's a trick to let TPπreturn complex numbers:π}ππtypeπ Float = Double;π TComplex = string[2*sizeof(float)];π { Complex number. Not a true string: the values are stored in binaryπ format within it. }ππ TCmplx = record { The internal storage format for TComplex }π len : byte;π r,i : float;π end;ππfunction Re(z:TComplex):float;πbeginπ Re := TCmplx(z).r;πend;ππfunction Im(z:TComplex):float;πbeginπ Im := TCmplx(z).i;πend;ππfunction Complex(x,y:float):TComplex;π{ Convert x + iy to complex number. }πvarπ result : TCmplx;πbeginπ with result doπ beginπ len := 2*sizeof(float);π r := x;π i := y;π end;π Complex := TComplex(result);πend;ππ{You can use these to build up lots of functions returning TComplex types.}π 40 01-27-9412:19ALL HARRY BAECKER Random Numbers SWAG9402 7 ₧8 {π> I would also like some possible suggestions on a good random generatorπ> function or Procedure that is easy to understand.π}πππ{ Given }ππvar Seed; {among your globals}ππ{ You could try seeding it with: }ππProcedure Randomise;ππvarπ hour, min, sec, sex100: word;π root: Longint;ππbeginππ GetTime(hour,min,sec,sec100); {from Dos or WinDos unit}π root := hour shr 1;π root := root * sec * sec100;π root := root shr 16;π Seed := LoWord(root); {needs WinAPI unit}πend;ππ{And to get a "random" integer in the range 0 to N - 1: }ππfunction Random(Target: Integer): Integer;ππvarπ work: Longint;ππbeginπ work := Seed * Seed;π work := work shr 16;π Seed := LoWord(work);π Random := Seed mod Target;πend;ππ 41 02-05-9407:56ALL FRANK BITTERLICH Setting BITS SWAG9402 7 ₧8 {π > This would seem like something simple but canπ > someone explain how toπ > calculate what is included in the followingπ > statement once I have readπ > the variable:πLooks like a user record of some BBS system or so...ππOr did you want to know how to check / set the bits? }ππFUNCTION GetBit (v, BitNumber: BYTE): BOOLEAN;π BEGINπ IF (v AND (1 SHL BitNumber))<>0 THENπ GetBit:=TRUEπ ELSEπ GetBit:=FALSE;π END; {Returns TRUE if specified bit is set }ππPROCEDURE SetBit (VAR v: Byte; BitNumber: Byte; SetReset: BOOLEAN);π BEGINπ IF SetReset THENπ v:=v OR (1 SHL BitNumber)π ELSEπ v:=v AND NOT (1 SHL BitNumber);π END;ππ 42 02-09-9407:25ALL DON PAULSEN Setting Bit Flags in ASM SWAG9402 64 ₧8 (*πDate: 02-05-95πFrom: DON PAULSENπππ This unit provides routines to manipulate individual bitsπ in memory, including test, set, clear, and toggle. You mayπ also count the number of bits set with NumFlagsSet, and getπ a "picture" of them with the function FlagString.ππ All the routines are in the interface section to provideπ complete low-level control of your own data space used forπ flags. Usually the oFlags object will be most convenient.π Just initialize the object with the number of flags required,π and it will allocate sufficient memory on the heap and clearπ them to zero.π*)πππUNIT DpFlags;ππ{$A+,B-,D-,E-,F-,G-,I-,L-,N-,O-,R-,S-,V-,X-}π{$IFDEF VER70} {$P-,Q-,T-,Y-} {$ENDIF}ππ(*π File(s) DPFLAGS.PASπ Unit(s) Noneπ Compiler Turbo Pascal v6.0+π Author Don Paulsenπ v1.00 Date 7-01-92π Last Change 11-12-93π Version 1.11π*)ππ{ Flags are numbered from left to right (low memory to high memory),π starting with 0, to a maximum of 65520. If the flags object isn't used,π use the System.FillChar routine to set or clear all the flags at once.π The memory for storing the flags can be allocated in the data segmentπ or on the heap.ππ Here are two methods for declaring an array for the flags (not needed ifπ the oFlags object is used):ππ CONSTπ cMaxFlagNumber = 50;π cNumberOfFlags = 51;ππ VARπ flags_A : array [0..(cMaxFlagNumber div 8)] of byte;π flags_B : array [0..(cNumberOfFlags - 1) div 8] of byte;ππ Note that since the first flag is flag 0, cNumberOfFlags is always 1 greaterπ than cMaxFlagNumber. }πππINTERFACEππPROCEDURE SetFlag (var flags; flagNum : word);πPROCEDURE ClearFlag (var flags; flagNum : word);πPROCEDURE ToggleFlag (var flags; flagNum : word);πFUNCTION FlagIsSet (var flags; flagNum : word): boolean;πFUNCTION NumFlagsSet (var flags; numFlags: word): word;πFUNCTION FlagString (var flags; numFlags: word): string;ππTYPEπ tFlags = ^oFlags;π oFlags = OBJECTπ CONSTRUCTOR Init (numberOfFlags: word);π PROCEDURE ClearAllFlags;π PROCEDURE SetAllFlags;π PROCEDURE SetFlag (flagNum: word);π PROCEDURE ClearFlag (flagNum: word);π PROCEDURE ToggleFlag (flagNum: word);π FUNCTION FlagIsSet (flagNum: word): boolean;π FUNCTION NumFlagsSet : word;π FUNCTION FlagString : string;π DESTRUCTOR Done;π PRIVATEπ flags : pointer;π numFlags : word;π END;πππIMPLEMENTATIONππ{=======================================================}πPROCEDURE SetFlag (var flags; flagNum: word); assembler;ππASMπ les di, flagsπ mov cx, flagNumπ mov bx, cxπ shr bx, 1π shr bx, 1π shr bx, 1π and cl, 7π mov al, 80hπ shr al, clπ or es:[di][bx], alπEND;ππ{=========================================================}πPROCEDURE ClearFlag (var flags; flagNum: word); assembler;ππASMπ les di, flagsπ mov cx, flagNumπ mov bx, cxπ shr bx, 1π shr bx, 1π shr bx, 1π and cl, 7π mov al, 7Fhπ ror al, clπ and es:[di][bx], alπEND;ππ{==========================================================}πPROCEDURE ToggleFlag (var flags; flagNum: word); assembler;ππASMπ les di, flagsπ mov cx, flagNumπ mov bx, cxπ shr bx, 1π shr bx, 1π shr bx, 1π and cl, 7π mov al, 80hπ shr al, clπ xor es:[di][bx], alπEND;ππ{=================================================================}πFUNCTION FlagIsSet (var flags; flagNum: word): boolean; assembler;ππASMπ les di, flagsπ mov cx, flagNumπ mov bx, cxπ shr bx, 1π shr bx, 1π shr bx, 1π and cl, 7π inc cxπ mov al, es:[di][bx]π rol al, clπ and al, 1π@done:πEND;ππ{=================================================================}πFUNCTION NumFlagsSet (var flags; numFlags: word): word; assembler;ππASMπ push dsπ cldπ lds si, flagsπ xor bx, bxπ mov cx, numFlagsπ mov dx, cxπ xor di, diπ shr cx, 1π shr cx, 1π shr cx, 1π jcxz @remainderπ@byte8:π lodsbπ shl al, 1; adc bx, diπ shl al, 1; adc bx, diπ shl al, 1; adc bx, diπ shl al, 1; adc bx, diπ shl al, 1; adc bx, diπ shl al, 1; adc bx, diπ shl al, 1; adc bx, diπ shl al, 1; adc bx, diπ loop @byte8π@remainder:π mov cx, dxπ and cx, 7π jz @doneπ lodsbπ@bit:π shl al, 1π adc bx, diπ loop @bitπ@done:π mov ax, bxπ pop dsπEND;ππ{==================================================================}πFUNCTION FlagString (var flags; numFlags: word): string; assembler;ππ{ Returns a string of 0's & 1's showing the flags. Note that at most 255π flags can shown in a string. Returns nul if numFlags is 0 or greaterπ than 255. }ππASMπ push dsπ cldπ lds si, flagsπ les di, @resultπ mov cx, numflagsπ or ch, chπ jz @okπ xor cx, cxπ@ok:π mov al, clπ stosb { length of string }π jcxz @doneπ mov dx, cxπ push dx { save number of flags }π mov ah, '0'π shr dl, 1π shr dl, 1π shr dl, 1π jz @remainderπ@byte8: { do 8 bits at a time }π lodsbπ mov bl, alπ mov cl, 8π@bit8:π mov al, ah { ah = '0' }π shl bl, 1π adc al, dh { dh = 0 }π stosbπ loop @bit8π dec dlπ jnz @byte8ππ@remainder: { do remaining (numFlags mod 8) bits }π pop dxπ mov cx, dxπ and cl, 7 { 0 <= cx <= 7 (number of flags in partial byte) }π jz @doneπ lodsb { last byte containing flags }π mov bl, alπ@bit:π mov al, ah { ah = '0' }π shl bl, 1π adc al, dh { dh = 0 }π stosbπ loop @bitπ@done:π pop dsπEND;ππ{=============================================}πCONSTRUCTOR oFlags.Init (numberOfFlags: word);ππBEGINπ if numberOfFlags > 65520 then FAIL;π numFlags:= numberOfFlags;π GetMem (flags, (numFlags + 7) div 8);π if flags = nil then FAIL;πEND;ππ{==============================}πPROCEDURE oFlags.ClearAllFlags;ππBEGINπ FillChar (flags^, (numFlags + 7) div 8, #0);πEND;ππ{============================}πPROCEDURE oFlags.SetAllFlags;ππBEGINπ FillChar (flags^, (numFlags + 7) div 8, #1);πEND;ππ{========================================}πPROCEDURE oFlags.SetFlag (flagNum: word);ππBEGINπ DpFlags.SetFlag (flags^, flagNum);πEND;ππ{==========================================}πPROCEDURE oFlags.ClearFlag (flagNum: word);ππBEGINπ DpFlags.ClearFlag (flags^, flagNum);πEND;ππ{===========================================}πPROCEDURE oFlags.ToggleFlag (flagNum: word);ππBEGINπ DpFlags.ToggleFlag (flags^, flagNum);πEND;ππ{==================================================}πFUNCTION oFlags.FlagIsSet (flagNum: word): boolean;ππBEGINπ FlagIsSet:= DpFlags.FlagIsSet (flags^, flagNum);πEND;ππ{=================================}πFUNCTION oFlags.NumFlagsSet: word;ππBEGINπ NumFlagsSet:= DpFlags.NumFlagsSet (flags^, numFlags);πEND;ππ{==================================}πFUNCTION oFlags.FlagString: string;ππVARπ w : word;ππBEGINπ w:= numFlags;π if w > 255 then w:= 255;π FlagString:= DpFlags.FlagString (flags^, w);πEND;ππ{======================}πDESTRUCTOR oFlags.Done;ππBEGINπ if flags <> nil then FreeMem (flags, (numFlags + 7) div 8);πEND;ππEND. { Unit DpFlags }ππ 43 02-09-9407:25ALL GAYLE DAVIS Hex String to LONGINT SWAG9402 16 ₧8 π{ You've probably seen a lot of code to convert a number to HEX.π Here is one that will take a hex String and covert it back to a numberππ The conversion is back to type LONGINT, so you can covert to WORDS orπ BYTES by simply declaring your whatever varible you want }ππ{$V-}πUSES CRT;ππVARπ A : LONGINT;π B : WORD;π C : BYTE;π D : WORD;ππ{ ---------------------------------------------------------------------- }ππFUNCTION HexToLong(S : STRING) : LONGINT;ππ FUNCTION ANumBin (B : STRING) : LONGINT; Assembler;π ASMπ LES DI, Bπ XOR CH, CHπ MOV CL, ES : [DI]π ADD DI, CXπ MOV AX, 0π MOV DX, 0π MOV BX, 1π MOV SI, 0π @LOOP :π CMP BYTE PTR ES : [DI], '1'π JNE @NotOneπ ADD AX, BX {add power to accum}π ADC DX, SIπ @NotOne :π SHL SI, 1 {double power}π SHL BX, 1π ADC SI, 0π DEC DIπ LOOP @LOOPπ END;ππCONSTπ HexDigits : ARRAY [0..15] OF CHAR = '0123456789ABCDEF';π Legal : SET OF Char = ['$','0'..'9','A'..'F'];π BinNibbles : ARRAY [0..15] OF ARRAY [0..3] OF CHAR = (π '0000', '0001', '0010', '0011',π '0100', '0101', '0110', '0111',π '1000', '1001', '1010', '1011',π '1100', '1101', '1110', '1111');ππVAR I : BYTE;π O : STRING;ππBEGINπO := '';πHexToLong := 0; { Returns zero if illegal characters found }πIF S = '' THEN EXIT;πFOR I := 1 TO LENGTH(S) DOπ BEGINπ IF NOT (S[i] in LEGAL) THEN EXIT;π O := O + binNibbles[PRED(POS(S[i],Hexdigits))];π END;πHexToLong := ANumBin(O)πEND;ππ{ ---------------------------------------------------------------------- }ππBEGINπClrScr;πA := HexToLong('$02F8');πB := HexToLong('$0DFF');πC := HexToLong('$00FF'); { The biggest byte there is !! }πD := HexToLong(''); { this is ILLEGAL !! .. D will be ZERO }πWriteLn(A,' ',B,' ',C,' ',D);πEND.