I suppose that we'll need to use mul when it comes to pointing to certain element in our array, since this is what my tutorial do: last_name db 15 dup (?) first_name db 15 dup (?) age db ? tel_no db 10 dup (?) address_book db 100 dup ( 41 dup (' ')) ; creates 100 ; entry in memory To point to entry 29th, address of age: mov bx, offset address_book mov ax, 28 ; entry (less 1) mov cx, 41 ; entry length mul cx mov di, ax ; move to pointer mov dl, WHat i dun understand is the usage of mul in this case. How would a mul serve it's purpose in helping us point to entry 29? This is what i have in mind: (entry 1) (entry 2) (entry 3).......(entry 29) 41bytes 41bytes 41bytes 41 bytes So, to get to the 29th entry, we need to bypass the previous 28 entries, thus 41 x 28, and we record it in di, and let it serve as a pointer, later mov dl, to get to age? Is this what mul is used for?
Posted on 2001-06-24 21:41:00 by JCL
That is correct. mul takes one operand:

mul   bl       ;AX=AH*BL
mul   cx       ;AX:DX=AX*CX
mul   eax      ;EAX:EDX=EAX*EAX
This message was edited by eet_1024, on 6/24/2001 10:22:43 PM
Posted on 2001-06-24 22:21:00 by eet_1024
Multiplication is very slow, and should really be avoided if possible. Possible is usually defined in this case by "is it constant?" It is, so we can do it faster, although with more instructions.

;eax = desired index
mov ecx, eax ;We need one spare register I'm using ecx
shl ecx, 5   ;ecx = index * 32
lea eax, 
             ;eax = index * 9 + offset of array
add eax, ecx ;eax = index * (9 + 32) + offset of array
If your code is speed critical, using LEA or SHL is usually faster than MULs. This is not so true for the Pentium4 for various reasons, and it is best to consult the Intel docs when optimising for a P4. In general however use LEA and SHL for constant multiplies. Mirno
Posted on 2001-06-25 04:45:00 by Mirno
OK, so mul is a slow instruction an should be minimised where ever possible. So, how should i use Lea for my code above? I'm not sure how to use it. Use EQU? I think using SHL is not possible in this case as for 41 * 28, we cannot use SHL, which limits multiplication to powers of 2 only? Maybe we can: result1 EQU 41 * 28 mov bx, offset address_book mov di, result1 mov dl, Would this code be faster than the one i have given originally?
Posted on 2001-06-25 07:13:00 by JCL
JCL, Mirno has shown you exactly what you want to do. His code shows how to multiply by 41 without using th mul instruction. Personal Observation: I've been using assembly on and off for the past year. One thing I knew when I decided to undertake assembly was this: FUNCTIONING BRAIN REQUIRED!!! Now JCL (and anybody else reading) Before you Post a request for information...think about exactly what you want to do, then have a go at it. If the answer eludes you or you want comments on your solution then post it here. Once you've gotten a reply read it then read it again. Try to implement any suggestions. When code samples are given in a reply it's usually a solutin to the specific question posed. By the way ...get a hold of the x86 OPCODES help file.
Posted on 2001-06-25 08:39:00 by pissed off
Hey, pissed off.Like i have declared, i'm still a newbie. Currently, my knowledge of ASM is still very limited, which is why I have to ask for help in clarifying my doubts. Also, what Mirno gave me is 32bit ASM(I would not say it's totally 32bit, except that it uses eax) With my current knowledge, it'll take more posts for me to ask him what he meant with the code. So, after realising that my thought of mul is correct, and getting the response that mul is not that good, I'm suggesting another solution and asking whether it would be better.So, whats wrong with it?
Posted on 2001-06-25 08:57:00 by JCL
By the way, the tutorial I have studied told me that LEA is slower than mov bx, offset address_book. Which is the reason by I'm suggesting this new solution. Thanx Mirno. After somemore studying of ur code, I realised what it does, but in your case, the element have to be 32bytes long for SHL to work, am i rite?
Posted on 2001-06-25 09:01:00 by JCL
JCL, in a way you're right. By aligning to some power of 2 boundary you can access data VERY quickly. It is wasteful though, and you can still get by without MUL, with only a few instructions extra (at some points it may be better using MUL, and you should think about each case as it occurs). As we know, the only "quick" way of multiplying is by using bit-shifting. By using this fact with simple maths, and instruction choice we can get rid of multiplying by constants (in most cases). Take your example - multiplying by 41: 41 = 32 + 8 + 1 32, 8, and 1 are all powers of 2, so we can get them easily! Whats more, the LEA instruction allows us to add two registers together, and shift one of those registers left by up to 3 bits (multiplying by 8). It also allows us to add a constant too!

LEA , [*<2,4,8> +  + ]
All three of the "" in the above example can be the same register. So it gives us the option of multiplying by 2, 3, 4, 5, 8, or 9 in one instruction, while adding a constant to it too. So using at most only one other register we can get:

LEA eax, 
SHL eax, 1               ; = eax * 6  ( = (eax * 3) * 2)

MOV ecx, eax
SHL eax, 3
SUB eax, ecx             ; = eax * 7  ( = (eax * 8) - eax)

LEA eax, 
SHL eax, 1               ; = eax * 10 ( = (eax * 5) * 2)
And so on! Mirno
Posted on 2001-06-25 10:37:00 by Mirno
One other thing to note, is that using a struct can vastly improve the readability of your code. It'll also make it easier to modify it! This example is in MASM format (I don't know TASM):

MyStruct STRUCT
  last_name   db 15 dup (?)
  first_name  db 15 dup (?)
  age         db         ?
  tel_no      db 10 dup (?)
MyStruct ENDS

address_book MyStruct 100 dup (<>)

.code
  ;blah blah
  ;mov blah, blah
  ;invoke blah, hWnd, null, blah, null
  mov dl, (MyStruct PTR ).age
You can also use the assume directive, but that can get confusing, I much prefere to use the above method as it makes code more understandable. Mirno
Posted on 2001-06-25 11:09:00 by Mirno
JCL,
"By the way, the tutorial I have studied told me that LEA is slower than mov bx, offset address_book."
from "How to optimize for the Pentium family of microprocessors" Copyright 1996, 2000 by Agner Fog. Last modified 2000-03-31. .... .... 27.1 LEA instruction (all processors) The LEA instruction is useful for many purposes because it can do a shift, two additions, and a move in just one instruction taking one clock cycle. Example: LEA EAX, is much faster than MOV EAX,ECX / SHL EAX,3 / ADD EAX,EBX / SUB EAX,1000 The LEA instruction can also be used to do an add or shift without changing the flags. The source and destination need not have the same word size, so LEA EAX, is a possible replacement for MOVZX EAX,BX, although suboptimal on most processors. You must be aware, however, that the LEA instruction will suffer an AGI stall on the PPlain and PMMX if it uses a base or index register which has been written to in the preceding clock cycle. Since the LEA instruction is pairable in the v-pipe on PPlain and PMMX and shift instructions are not, you may use LEA as a substitute for a SHL by 1, 2, or 3 if you want the instruction to execute in the V-pipe. The 32 bit processors have no documented addressing mode with a scaled index register and nothing else, so an instruction like LEA EAX, is actually coded as LEA EAX, with an immediate displacement of 4 bytes. You may reduce the instruction size by instead writing LEA EAX, or even better ADD EAX,EAX. The latter code cannot have an AGI delay in PPlain and PMMX. If you happen to have a register which is zero (like a loop counter after a loop), then you may use it as a base register to reduce the code size:

LEA EAX,     ; 7 bytes
LEA EAX, ; 3 bytes
So,the usage of a LEA is: 1. To load some memory effective address Example:

     lea ebx, address_book
2. For "fast" arithmetic calculations - LEA uses 1 CPU cycle too Examples:

     mov eax, 3
     mov ecx, 7
 
1. lea ebx,       ; ebx=3.2=6 Mult. eax by  2
2. lea ebx,     ; ebx=3.2+5=11 Mult. eax by 2 plus 5 
3. lea ebx,     ; ebx=3.2-5=1 Mult. eax by 2 minus 5 
4. lea ebx, ; ebx=3.2+7+5=18 Mult. eax by 2 plus ecx plus 5 
5. lea ebx, ; ebx=3.2+7.2+111=131 Mult. eax by 2 plus ecx by 2 plus 111
6. lea ebx, ; ebx=3.4+7.2-12=14 Mult. eax by 4 plus ecx by 2 minus 12
7. lea ebx, ; ebx=3.8+7.4-12=40 Mult. eax by 8 plus ecx by 4 minus 12
8. lea ebx, ; ebx=3.8+7.8-3=77 Mult. eax by 8 plus ecx by 8 minus 3
9. lea eax,  ; eax=3+1=4 ; it is INC eax 
10.lea eax,  ; eax=3-1=2 ; it is DEC eax

11. Multiplying by 10 -> (eax.5).2
    lea eax,  ;  eax=3.4+3=15 -> Multiplying by 5
    lea eax,      ;  eax=15.2=30  -> Multiplying by 2

12. Multiplying by 100 -> ((eax.5).5).4 
    lea eax,  ;  eax=3.4+3=15 -> Multiplying by 5
    lea eax,  ;  eax=15.4+15=75 -> Multiplying by 5
    lea eax,      ;  eax=75.4=300  -> Multiplying by 4 
or

    lea eax,  ;  eax=3.4+3=15 -> Multiplying by 5
    lea eax,  ;  eax=15.4+15=75 -> Multiplying by 5
    shl eax, 2           ;  eax=75.4=300  -> shl Multiplying by 4 
and just 3 rules: 1.U can use in brackets 1 or 2 registers only (no more). example:

  lea eax, -> is wrong cos we use 3 registers (edx, ecx,ebx)  
  lea eax, -> is correct cos we use 2 registers (edx, ecx) 
2. the signs of registers in brackets must be plus example:

   lea eax, -> is wrong cos we use -ecx*2  
   lea eax, -> is correct cos we use +ecx*2 (edx*4 is plus too)
3. the scale value of registers in brackets must be 2 or 4 or 8. example:

  lea eax, -> is wrong cos we use ecx*
Posted on 2001-06-25 12:39:00 by buliaNaza
You can only shift one of the two registers in the LEA.

LEA eax, 
Does not work: "C:\temp\ab\a.asm(25) : error A2030: multiple index registers not allowed" Mirno
Posted on 2001-06-25 13:05:00 by Mirno
hah, hah, hah... thanks Mirno for the corrections of my "provocation" examples... I'm sure you know how to use lea..hah, hah.. I am wrong you are right, but I need to receive such replay from a newbie.... It will be a proof he/she has interested... Just out of interest, does the name Mirno have an opposite?
Posted on 2001-06-25 14:35:00 by buliaNaza
buliaNaza, I got the name Mirno from a brand of Vodka called "Smirnoff", which I used to drink when I was 17. One morning the light hit a bottle in such a way that only lit some of the letters: Smirnoff So an opposite isn't really applicable :P Since then, I found its also a Yugoslavian name or something! Also my little brother nicked my name for his band. Mirno
Posted on 2001-06-26 06:54:00 by Mirno
Thanks Mirno and BuliaNaza for giving me such detailed explanation. I have saved all your pointers and would slowly go through them so as to optimise my use of LEA in the future! Meanwhile, I'll continue sloggin thru my tutorial.
Posted on 2001-06-26 13:34:00 by JCL
Thanks Mirno, it's cool... do you have other posts as this1? excuse my curiosity, but it is so short and elegant..

  ......
  ......  
  mov edx, buf    ; edx is pointer to our buffer base
  xor eax, eax    ; EAX holds the checksum 
@@:
  adc eax, 
  dec ecx
  jnz @B 
  
  .......
  ....... 
  
------------------- "In this world, there are three kinds of people: Those who can be put into one of two groups, and those who are in the groups yet"
Posted on 2001-06-26 14:24:00 by buliaNaza