Mega Code Archive

 
Categories / Delphi / Examples
 

Using data in pointers, the assembler way

Title: Using data in pointers, the assembler way Question: typecasting or increasing pointer values "the delphi way" can sometimes seem tough. Using some plain and simple assembler functions can make it all easier. Answer: Lets say you want to write the value "$FF0080AA" at a certain position (offset 10) in a block of data pointed to by the pMyData pointer. One way to do it is: procedure TForm1.Button1Click(Sender: TObject); var pMyData : pointer; dwData : DWord; dwOffset : DWord; begin GetMem(pMyData,20); try dwData := $FF0080AA; dwOffset := 10; DWord(ptr(integer(pMyData) + dwOffset)^) := dwData; finally FreeMem(pMyData,20); end; end; Since a PC uses Little-Endian(LSB first) it will make the memory look like this: [pMyData + 10] = $AA; [pMyData + 11] = $80; [pMyData + 12] = $00; [pMyData + 13] = $FF; Ok, not to hard it seams, but ugly and complicated. And what if we need the value to be written in BigEndian format (MSB first)? PC's use Little Endian format - that is putting the LSB-byte (Low Significant Byte) first. Needing BigEndian makes it a little more tough for us to write in one line of good looking Delphi code. In Big-Endian the result from the above operation would have been: [pMyData + 10] = $FF; [pMyData + 11] = $00; [pMyData + 12] = $80; [pMyData + 13] = $AA; These things are actually pretty basic stuff, and shouldn't be that hard to perform. But in Delphi it becomes a mess. I therefore created some tight and neat assembler functions that do all this things for me. They also make it easier to use Little-Ednian and do "normal" read/write operations on a data block, by only supling a pointer, an offset and the value to be written or read. Writing assembler functions in Delphi is a beautiful thing. The first three parameters are placed into EAX, EDX and ECX (in that order). The result is always the value placed in the EAX register. --- unit ReadWriteBELE; interface // WRITE OPERATIONS procedure SetDWord(Data : Pointer; Offset : integer; Value : DWord); procedure SetDWordBE(Data : Pointer; Offset : integer; Value : DWord); procedure SetWord(Data : Pointer; Offset : integer; Value : Word); procedure SetWordBE(Data : Pointer; Offset : integer; Value : word); procedure SetByte(Data : Pointer; Offset : integer; Value : byte); // READ OPERATIONS - Always returns LE values function GetDWord(Data : Pointer; Offset : integer) : DWord; function GetDWordBE(Data : Pointer; Offset : integer) : DWord; function GetWord(Data : Pointer; Offset : integer) : Word; function GetWordBE(Data : Pointer; Offset : integer) : Word; function GetByte(Data : Pointer; Offset : integer) : byte; implementation // Little-Endian format, (LSB first, normal order in a PC) procedure SetDWord(Data : Pointer; Offset : integer; Value : DWord); assembler; asm // Increase the pointer by the value contained in EDX (Offset parameter) ADD EAX, EDX // Write the value in ECX to the memory address contained in EAX MOV [EAX], ECX end; // WARNING! Big-Endian format, (MSB first) procedure SetDWordBE(Data : Pointer; Offset : integer; Value : DWord); assembler; asm // Increase the pointer by the value contained in EDX (Offset parameter) ADD EAX, EDX // Swap bytes, so it becomes BE order BSWAP ECX // Write the value in ECX to the memory address contained in EAX MOV [EAX], ECX end; // Little-Endian format, (LSB first, normal order in a PC) procedure SetWord(Data : Pointer; Offset : integer; Value : Word); assembler; asm // Increase the pointer by the value contained in EDX (Offset parameter) ADD EAX, EDX // Write the value in CX (16-bit) to the memory address contained in EAX MOV [EAX], CX end; // WARNING! Big-Endian format, (MSB first) procedure SetWordBE(Data : Pointer; Offset : integer; Value : word); assembler; asm // Increase the pointer by the value contained in EDX (Offset parameter) ADD EAX, EDX // Swap bytes, so it becomes BE order in CX XCHG CL, CH // Write the value in CX (16-bit) to the memory address contained in EAX MOV [EAX], CX end; procedure SetByte(Data : Pointer; Offset : integer; Value : byte); assembler; asm // Increase the pointer by the value contained in EDX (Offset parameter) ADD EAX, EDX // Write the value in CL (8-bit) to the memory address contained in EAX MOV [EAX], CL end; // Little-Endian format, (LSB first, normal order in a PC) function GetDWord(Data : Pointer; Offset : integer) : DWord; assembler; asm // Increase the pointer by the value contained in EDX (Offset parameter) ADD EAX, EDX // Read the value contained in the memory address contained in EAX into EAX MOV EAX, [EAX] end; // WARNING! Big-Endian format, (MSB first) function GetDWordBE(Data : Pointer; Offset : integer) : DWord; assembler; asm // Increase the pointer by the value contained in EDX (Offset parameter) ADD EAX, EDX // Read the value contained in the memory address contained in EAX into EAX MOV EAX, [EAX] // Swap bytes so result becomes LE order BSWAP EAX end; // Little-Endian format, (LSB first, normal order in a PC) function GetWord(Data : Pointer; Offset : integer) : Word; assembler; asm // Increase the pointer by the value contained in EDX (Offset parameter) ADD EAX, EDX // Read the value contained in the memory address contained in EAX into AX (16-bit) MOV AX, [EAX] end; // WARNING! Big-Endian format, (MSB first) function GetWordBE(Data : Pointer; Offset : integer) : Word; assembler; asm // Increase the pointer by the value contained in EDX (Offset parameter) ADD EAX, EDX // Read the value contained in the memory address contained in EAX into AX (16-bit) MOV AX, [EAX] // Swap bytes so result becomes LE order XCHG AL, AH end; function GetByte(Data : Pointer; Offset : integer) : byte; assembler; asm // Increase the pointer by the value contained in EDX (Offset parameter) ADD EAX, EDX // Read the value contained in the memory address contained in EAX into AL (8-bit) MOV AL, [EAX] end; end. --- (of course, there are no safety what so ever using these function. If you pass a offset outside your allocated data, then you may end up with a nice blue screen in worst case) Dr. William T has written a nice articleabout Big vs Little endian order. http://www.cs.umass.edu/~verts/cs32/endian.html