Core procedures

Having taken care of all the output format specifics, we may safely proceed to the implementation of the core's code. As it has already been mentioned earlier, we are about to export only a single entry; however, we still need to implement the rest. There are only four procedures in our core:

  • f_set_data_pointer: This procedure accepts a single parameter, which is a pointer to the data we want to process, and stores it to the data_pointer global variable
  • f_set_data_length: This procedure accepts one parameter, which is the length of data we want to encrypt/decrypt, and stores it to the data_length global variable
  • f_encrypt: This procedure implements the encryption loop
  • f_decrypt: This is the inverse operation of f_encrypt

However, prior to implementing all of these, we first need to prepare the template or, to be more precise, the skeleton for our main source file. This template would look a tiny bit different from what we are used to due to the extensive usage of macroinstructions. However, don't let it confuse you. The structure is logically (and from an Assembler's point of view) the same as the one we have been dealing with earlier:

; First of all we need to include all that we have written this far
include 'platform.inc'

; The following variable and macro are used in compile time
; only for generation of
pseudorandom sequences, where
; count specifies the amount of pseudorandom bytes to
generate
seed = %t
macro fill_random count
{
local a, b
a = 0
while a < count
seed = ((seed shr 11) xor (seed * 12543)) and 0xffffffff
b = seed and 0xff
db b
a = a + 1
end while
}

; ACTIVE_TARGET variable may be set to any of the
; TARGET* constants

ACTIVE_TARGET = TARGET_W32_DLL

; Tell the compiler which type of output is expected
; depending on the value of
the ACTIVE_TARGET variable
set_output_format

; Create code section depending on selected target
begin_code_section

; We will insert our code here

; Create appropriate declaration of the data section
begin_data_section

; Tell the compiler whether we are expecting 32-bit
; or 64-bit output

if(ACTIVE_TARGET = TARGET_W32_OBJ) |
(ACTIVE_TARGET = TARGET_W32_DLL) |
(ACTIVE_TARGET = TARGET_L32_O)
use32
else if(ACTIVE_TARGET = TARGET_W64_OBJ) |
(ACTIVE_TARGET = TARGET_W64_DLL) |
(ACTIVE_TARGET = TARGET_L64_O)
use64
end if

; This, in fact, is a structure which would be populated with
; addresses of our procedures

pointers:
fill_random 4 * 8

; Here the core stores the address of the data to be processed
data_pointer:
fill_random 8

; And here the core stores its length in bytes
data_length:
fill_random 8

; Pseudorandom encryption key
key:
fill_random 2

; The following line may be omitted if we used the postpone
; directive instead of "macro finalize"
finalize

Despite having a different look from what we are used to seeing, the preceding code is quite self-explanatory and there is not too much to add, if at all. All the hard work is being delegated to previously defined macroinstructions and the only aspect we still have to take care of is the bit capacity. As you can see, the size and addresses are given 8 bytes by default. The purpose of this is to make them fit both 32-bit and 64-bit needs. We could have inserted another if…else clause, but since we only have 3 bit capacity-dependent data items, spending another 4 bytes for each of them in 32-bit mode is not an issue.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset