0

I want to get 2 different things:
(1) the (value at bp) plus 16 (mathematical addition) something similar to: mov ax, [bp] + 16
(2) the value of bp+16 (the address bp+16)

in order to get (1) I tried:

mov ax, bp+16  

But it gave an error.

for (2) I tried:

mov ax, [bp+16]  

Which worked. (I hope I did it correctly)..


Why can't assembly understand the evaluation of:

mov ax, bp+16

But can understand:

mov ax, [bp+16]  

because addition is not defined using the + sign, so what happens behind the scenes there?

CodeCop
  • 1
  • 2
  • 15
  • 37

1 Answers1

5

There's no form of mov that does math to produce a new value for the destination register that wasn't in a source register or memory operand. https://www.felixcloutier.com/x86/mov. The value you want in AX has to be an immediate, or contained directly in a register or in memory at some address.

If you want the value bp+16 instead of the memory at that address, use lea ax, [bp+16] instead of mov. Load Effective Address does the address calculation and then puts that address in the destination register, instead of loading from it. LEA is just a math instruction that uses memory-operand syntax and machine-encoding. It's convenient as a copy-and-add. (Or with 32-bit addressing modes, also shifting.)

(In terms of full seg:off x86 addressing, LEA only does the "offset" part, the "effective address"; it doesn't add the segment base so SS:BP vs. DS:DI or whatever is irrelevant.)

Doing mov ax, [bp+16] is valid because [] means dereference as a memory operand, and x86 16-bit addressing modes support register + displacement.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • So basically `lea ax, [bp+16]` is for the case (1) (which is: storing in ax the value of bp, then adding 16) ? thank you sir. – CodeCop May 21 '20 at 00:17
  • @StackOMeow: your question seems to have its definitions backwards or self-conflicting. You wrote "(1) the value *at* bp plus 16". "at" would imply using it as a memory operand. But yes, LEA is just a math instruction that uses memory-operand syntax and machine-encoding. – Peter Cordes May 21 '20 at 00:20
  • If I were to try and write (1) as a bad assembly code it would be `mov ax, [bp] + 16` (so moving the content that at address bp , then adding to that number 16) – CodeCop May 21 '20 at 00:22
  • @StackOMeow: Oh, I see what you want now. x86 can't do that with one instruction. You could `mov ax, 16` / `add ax, [bp]`, but that's not better than `mov ax, [bp]` / `add ax, 16`. You should use that `[bp] + 16` notation to clarify your question. – Peter Cordes May 21 '20 at 00:23
  • `lea` is the one exception to the rule. It doesn't dereference anything at all. I don't know why this is, and it's very misleading, but when you do `lea ax,[bp+16]` you get the same register state as doing `mov ax,bp` followed by `add ax,16` except the flags are the same after the `lea` as they were before. Either way, no values in RAM were changed, only registers. – puppydrum64 Dec 21 '22 at 17:08
  • @puppydrum64: It's not "misleading" if you know what Load Effective Address means. As for why it exists, probably because the CPU can already decode the machine-code format for addressing modes, so it was cheap to implement by just doing something different with the result of address-generation. Stephen Morse (architect of the 8086 ISA) explains the design intent in his book, The 8086 Primer, available for free on his web site. https://stevemorse.org/8086/ page 41 and 42. He describes it as being designed to get pointers to variables. – Peter Cordes Dec 21 '22 at 21:32
  • A better way to think of it is just a math instruction which takes advantage of the machine code's ability to encode these operations (and in 386, also a shift). There's no need for the address to be valid, and in fact `lea bx, [static_var]` (4 bytes) is inefficient vs. `mov bx, OFFSET static_var` (3 bytes) so it's not good for taking the addresses of static locations without an index. It's useful for addresses of stack variables or array elements, though. – Peter Cordes Dec 21 '22 at 21:34