# How to use SHL/SAL, LEA and Add for arithmetic operations

I'm having problem computing the following arithmetic questions using SHL/SAL, LEA and ADD, and hoping someone can help explain or find the best ways to apply those:

• Multiply a variable by 24
• Multiply a variable by 1000
• Sounds a bit like homework/assignment. Commented Feb 23, 2022 at 10:17

SHL and SAL are the same instruction, they do the same: Shift bits to the left.

Shifting bits to the left is equivalent to multiplying by two.

For example, if you have the number 3 in the register AX, it would look something like this:

mov ax, 3 ; ax = 3 = 0000 0000 0000 0011
sal ax, 1 ; ax = 6 = 0000 0000 0000 0110

LEA allows you to perform a memory-addressing computation in the instruction, so you can use it to calculate an effective address (without accessing it).

For example:

mov rax, 0x100
mov rdi, 0x200
lea rax, [rax + rdi*2 + 0x10]
; rax = rax + rdi*2 + 0x10
; rax = 0x100 + 0x200*2 + 0x10
; rax = 0x100 + 0x400 + 0x10
; rax = 0x510

However, not all operations are valid addressing modes, you should check Intel SDM Volume 1 "Basic Architecture":

Multiply a variable by 24.

With shifts you can only multiply by powers of two, the same happens with lea, however, you know that 24 = 3*8, so you could do add 3 times the variable, and then multiply it by 8.

; rax = var
lea rax, [rax + rax*2] ; rax = 3*var
sal rax, 3             ; rax = 3*var*8

For 1000 we could do something similar, we know that 1000 is 2*5*2*5*2*5

lea rax, [rax + rax*4] ; rax = 5*var
lea rax, [rax + rax*4] ; rax = 5*5*var
lea rax, [rax + rax*4] ; rax = 5*5*5*var
sal rax, 3             ; rax = 8*125*var = 1000*var

An alternative could be:

lea rdi, [rax + rax*2] ; rdi = 3*var
sal rax, 7             ; rax = var*128
sub rax, rdi           ; rax = var*128 - var*3 = var * 125
sal rax, 3             ; rax = var*125 * 8