15

As the web-resources on this is sparse, I will, for the benefit of future searches, begin by listing the address modes for IA-32 Assembly Language (NASM) and then follow up with a quick question.

  1. Register addressing
    • mov eax, ebx: Copies what is in ebx into eax
    • mov esi, var: Copies address of var (say 0x0040120e) into esi
  2. Immediate addressing (second operand is an immediate constant)
    • mov bx, 20: 16-bit register bx gets the actual value 20
  3. Direct memory addressing (directly loads from memory through a specified address)
    • mov ax, [1000h]: loads a 2-byte object from the byte at address 4096 (0x1000 in hexadecimal) into a 16-bit register called 'ax'
    • mov [1000h], ax: memory at address 1000h gets the value of ax
  4. Direct offset addressing (same as 3, just using arithmetics to modify address)
    • mov al, [byte_tbl+2]
  5. Register indirect (accessing memory by using addresses stored in registers)
    • mov ax, [di]: copies value at memory address specified by di, into ax
    • mov dword [eax], var1: copies value in var1 into the memory slot specified by eax

Please note that the above is for NASM. For MASM/TASM you'd use "mov esi, OFFSET foo" to get the address, while "mov esi, foo" and "mov esi, [foo]" both would get the value (creds to @Michael).

So, onto my question. It is in in relation to an example at the bottom of page 29 of the following tutorial: http://www.tutorialspoint.com/assembly_programming/assembly_tutorial.pdf

It basically lists the below code as an example of indirect memory addressing.

MY_TABLE TIMES 10 DW 0 ; Allocates 10 words (2 bytes) each initialized to 0 
MOV EBX, [MY_TABLE] ; Effective Address of MY_TABLE in EBX 
MOV [EBX], 110 ; MY_TABLE[0] = 110 
ADD EBX, 2 ; EBX = EBX +2 
MOV [EBX], 123 ; MY_TABLE[1] = 123 

My questions:

  1. Should not "MOV EBX, [MY_TABLE]" in fact be "MOV EBX, MY_TABLE", as we want to put the address of the table in EBX, not the value itself?
  2. Surely it is MY_TABLE[2] that is equal to 123 at the end, not MY_TABLE[1]?
Magnus
  • 6,791
  • 8
  • 53
  • 84
  • The web resources are sparse?! The [Intel manual](http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html) explain all this in great detail. – Kerrek SB Dec 16 '13 at 12:46
  • 2
    I did quite a bit of searching and did not think it was straight forward to find a list with simple examples, in particular one that had the example in the second sub-bullet to the first main point. So in case someone else finds themselves in my shoes, or are confused by the difference between NASM/MASM/TASM on this topic, they might find the summary useful. – Magnus Dec 16 '13 at 13:06
  • See also http://stackoverflow.com/a/34058400/224132 for a rundown on addressing modes. And other links in http://stackoverflow.com/tags/x86/info – Peter Cordes Feb 10 '16 at 11:19
  • 2
    Thanks a lot! Intel goes about this _depth_, but this simple explanation helped me a lot. – Sebb May 07 '16 at 13:23
  • That tutorial is not valid NASM code. `MOV [EBX], 110 ` won't assemble because neither operand implies an operand-size. (I think even MASM won't assemble it.) – Peter Cordes Nov 29 '17 at 20:32

2 Answers2

7
  1. In NASM syntax, that instruction should be MOV EBX, MY_TABLE. What MOV EBX, [MY_TABLE] would do is load the first 4 bytes located at MY_TABLE into EBX. Another alternative would be to use LEA, as in LEA EBX, [MY_TABLE].

  2. In this case the tutorial is right. MY_TABLE is defined as an array of words. A word on the x86 is 2 bytes, so the second element of MY_TABLE is indeed located at MY_TABLE + 2.

Michael
  • 57,169
  • 9
  • 80
  • 125
  • 1. Does it load the first 4 bytes because the mov instruction always copies 32 bit on IA-32? Why is that? 2. Ah, so does +2 mean add 2 bytes? – Magnus Dec 16 '13 at 11:29
  • 1. It loads 4 bytes because the destination register is `EBX`, which is 4 bytes in size. 2. Right. If `MY_TABLE` was located at address 0 and you did `MOV EBX, [MY_TABLE+2]` you'd be reading the DWORD starting at address 2. There's no implicit scaling of offsets like in C. – Michael Dec 16 '13 at 11:37
  • But, if you scroll up on the same page of the pdf tutorial it says that word_table+3 also gives element 4. Is that not right then? – Magnus Dec 16 '13 at 11:53
  • Yes, `WORD_TABLE+3` would not get the 4th element of `WORD_TABLE`. – Michael Dec 16 '13 at 12:20
  • Can you take a look at this? http://stackoverflow.com/questions/29708532/why-isnt-my-assembly-program-setting-r1-to-the-correct-value – committedandroider Apr 18 '15 at 00:29
0

That tutorial is not even valid NASM code. For links to x86 guides / resources / manuals that don't suck, see the x86 tag wiki here on SO.

MOV [EBX], 110 won't assemble because neither operand implies an operand-size. (I think even MASM won't assemble it, but some bad assemblers like emu8086 have a default operand size for instructions like this.) mov word [ebx], 110 would do a 16-bit store.

MOV EBX, [MY_TABLE] will assemble but it loads the first 2 words from the table. mov ebx, MY_TABLE will put the address into a register.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847