Hi,
I just located
; add one to the task number, then mask to make sure we stay under 255
inc ebx
and ebx, 0x000000FF
; We use a couple tricks here below for speed. First, we're calling an internal List Manager function directly instead
; of going through the slower public interface. This bypasses the parameter checking that's normally performed, but
; that's okay since we are managing the input internally, so we know it will be correct. Second, we use the EBX
; register to track the current task number we're testing. Why EBX? Because LM_Internal_ElementAddressGet() doesn't
; modify it, so we don't need to save it here, saving us a handful of CPU cycles.
; get that task number's starting address
push ebx
push dword [tSystem.listTasks]
call LM_Internal_ElementAddressGet
pop esi
let me share some observations:
1st, efficiency.
this loop is executed on average 256/numberOfActiveTasks times.
assuming 5 active tasks, this is 50 iterations to find the task to switch to.
this is inefficient, even if you count the cycles of each single instruction.
2nd, bug
ebx will eventually be 255.
after
inc ebx, and ebx, 0x000000FF
ebx will be 0. unfortunately LM_Internal_ElementAddressGet will not return a valid
task, but some (more or less) random location somewhere. as this is treated as a task
this is a bug.
3rd, calling conventions
call LM_Internal_ElementAddressGet
pop esi
returning results on the stack is inefficient. return results through a register. EAX has been the register
to be used for resultgs for ages.
4th, more calling conventions
; Why EBX? Because LM_Internal_ElementAddressGet() doesn't
; modify it, so we don't need to save it here, saving us a handful of CPU cycles.
standard C calling conventions require that EBP, ESI, EDI are preserved across calls.
this serves the same purpose (efficiency), but has not to rely on undocumented features of
LM_Internal_ElementAddressGet.
5th, use efficient assembler (LM_Internal_ElementAddressGet)
replace
; check that the element requested is within range
; so first we get the number of elements from the list itself
mov esi, [ebp + 8]
mov eax, [tListInfo.elementCount]
; adjust eax by one since if a list has, say, 10 elements, they would actually be numbered 0 - 9
dec eax
; get the size of each element in this list
mov eax, [tListInfo.elementSize]
; calculate the new destination address
mov edx, [ebp + 12]
mul edx
add eax, esi
add eax, 16
with
; check that the element requested is within range
; so first we get the number of elements from the list itself
mov esi, [ebp + 8]
; get the size of each element in this list
mov eax, [tListInfo.elementSize]
; calculate the new destination address
mul [ebp + 12]
lea eax, [eax + esi + 16]
6th, use efficient assembler
replace
; set address of the thing to print info on what we found,
mov eax, [tSystem.configBits]
and eax, 000000000000000000000000000000010b
cmp eax, 000000000000000000000000000000010b
jne .NoPrint
by
; set address of the thing to print info on what we found,
test [tSystem.configBits], 000000000000000000000000000000010b
jne .NoPrint
7th, kFalse and kTrue are constants unlikely to ever change
replace
kTrue dd 0x00000001
kFalse dd 0x00000000
mov eax, [kTrue]
...
cmp eax, [kTrue]
by
%define kTrue 1
%define kFalse 0
mov eax, kTrue
...
cmp eax, kTrue
accessing memory is inefficient, compared to constants.
8th, bug
LMElementValidate will *always* return [kTrue].
Tom