Search code examples
assemblyx86-16tasm

Save value in byte of var in assembly


I want to make a program that takes 10 characters from the user and saves them in a vector DATA, but I get the error

can't add relative quantities

in mov byte ptr DATA[pos], al when I try to store the value.
How to solve this error?

 .model small
 .stack 100h
 .data
   DATA db 10 dup(?)
   cont db 010h
   pos db 0h
   msg db 10,13,7, 'Input: ', '$'

.code
 mov ax, @data
 mov ds, ax
 mov es, ax

mov ah, 09h
lea dx, msg
int 21h

cicle:  
  mov ah, 01h
  int 21h

  mov byte ptr DATA[pos], al   ;Save ASCII char in position pos in DATA

  inc pos
  dec cont 
jnz cicle

Solution

  • x86 doesn't have memory-indirect addressing modes that can load an index from memory. Keep your index in a register like a normal person, that's what registers are for.

    Or use a pointer increment and compare against an end-pointer.

    You don't need static storage for cont either. It's an assemble-time constant which you've chosen to hard-code as 10h, i.e. 16, which is larger than the amount of space you reserved for DATA... So that's just a bug which goes away if we simply put a label after DATA, or let the assembler calculate its size.

    Comparing a register against a label uses the address as an immediate, not loading a value from memory.

     .model small
     .stack 100h
     .data
       DATA db 10 dup(?)
       DATA_END:
       data_size = $ - DATA       ; or if you want the size in bytes, you can do this
    
       msg db 10,13,7, 'Input: ', '$'
    
    
    .code
     mov ax, @data
     mov ds, ax
     mov es, ax
    
    mov ah, 09h
    mov dx, OFFSET msg    ; There's no reason to use LEA for putting static addresses into registers, except with x86-64 RIP-relative addressing.  MOV is shorter and more efficient.
    int 21h
    
    
    mov  di, OFFSET DATA
    mov  ah, 01h         ; we can hoist this out of the loop because we don't destroy AH
    
    cicle:               ; do {
      int  21h
    
      mov  [di], al         ;Save ASCII char into DATA
    
      inc  di
      cmp  di, OFFSET DATA_END
      jb   cicle         ; }while(p < end_pointer);