Search code examples
assemblyx86-16tasmdosboxarray-indexing

My names are not being erased from the list. Assembly language x86


scrienume label let's me read from the keyboard 5 char names.The lista label displays each on one line along with their index(eg:if i write "daria" and "adria", the output is "1.daria", and on the next line is "2.maria"). The 3rd label should give me the possibility to write an index number from the keyboard and delete that has that index(eg:if i press 1 the name "daria" is deleted and the name "maria" gets the index 1).

These are the labels for input and output.

I tried to see in my program the location where i find the location of the index written from the keyboard and then move to the left in the string all the names that have an index bigger than the index i wrote.My problem is that my names are not being deleted from the list.This should erase a name from the list by id

scrienume:
  mov  dx, offset prompt
  mov  ah, 09h
  int  21h
  mov  cx, 5
  mov  si, numePointer
read_char:
  mov  ah, 01h
  int  21h
  mov  [si], al
  inc  si
  loop read_char
  mov  byte ptr [si], '$'
  inc  si
  mov  numePointer, si ; numePointer += 6
  jmp  bucla

lista:
  mov  dx, offset nume
print_names:
  push dx                        ; (1)
  mov  dx, offset numeIndex
  mov  ah, 09h
  int  21h
  inc  byte ptr [numeIndex + 2]  ; "1" -> "2" -> "3" ...
  pop  dx                        ; (1)

  mov  ah, 09h
  int  21h
  add  dx, 5 + 1
  cmp  dx, numePointer ; check if the current name is the last one
  jb   print_names
  jmp  bucla           ; return to main loop


sterge:
; Prompt user for index of name to delete
mov dx, offset string
mov ah, 09h
int 21h
; Read index from user
mov  ah, 01h
int  21h
sub al, '0'
mov al, al
mov bx, ax;

; Verify that index is valid
cmp bx, numes
jae invalidIndex

; Shift names to the left
mov cx, numes
mov si, numePointer
add si, bx
add si, bx
add si, bx
add si, bx
add si, bx
add si, 1
mov di, si
dec bx
dec numes
shiftLoop:
cmp bx, 0
je updatePointer
mov al, [si]
mov [di], al
inc si
inc di
dec bx
jmp shiftLoop

updatePointer:
mov numePointer, di
jmp bucla

invalidIndex:
; Display error message
mov dx, offset invalid
mov ah, 09h
int 21h
jmp bucla

Solution

  • Troubles in sterge

    sub al, '0'
    mov al, al
    mov bx, ax;
    cmp bx, numes
    jae invalidIndex
    

    The way this is written, it will always jump to invalidIndex. Apparantly your numes (names in the list) variable is word-sized and you would like to extend the byte-sized response from the user to a full word. mov al, al does not do that, you need mov ah, 0 (or cbw for these very small positive numbers).
    For a solution consider this: although the user will work with indexes starting at 1, the program should be using 0 as the first index as it will simplify things a lot.

    sub  al, '0'     ; AL=[1,9]
    cbw              ; AX=[1,9]   1-based index
    dec  ax          ; AX=[0,8]   0-based index
    cmp  ax, numes   ; numes is [0,9]
    jae  invalidIndex
    
    mov di, si
    

    You are setting up for your shiftloop with identical pointers for the source and the destination! Any work the loop might do will not matter that way!

    mov si, numePointer
    

    You are not using the numePointer the way I defined and used it in my previous answer(s).
    This is a pointer that contains the address of the end of the list of names.

    elena$maria$daria$adria$
    ^                       ^
    nume                    [numePointer]
    
    shiftLoop:
    cmp bx, 0
    je updatePointer
    

    You are using the index in BX to control the number of iterations. Each of your iterations just moves a single byte where in fact you should be moving 6 bytes (5 + 1), so you're copying not nearly enough!

    Solution for sterge

    Let's assume there are 4 names on the list, so numes=4:

    1.elena
    2.maria
    3.daria
    4.adria
    

    Valid user inputs would be 1, 2, 3, and 4 and the validation code will turn this into AL ranging from 0 to 3.
    Multiplying this number by 6 will give us the offset in the list where we find the name that is to be deleted. The part of the list that needs to be shifted down in memory then starts 6 bytes above that. It is possible for this part to be empty if the topmost item was selected for deletion. My code below uses the rep movsb instruction that will work fine even if there's nothing to copy.

      ...
    
      sub  al, 49      ; AL=["1","9"] 1-based input -> AL=[0,8] 0-based index
      mov  ah, 6
      mul  ah          ; -> AX = {0,6,12,18,24,30,36,42,48}
      add  ax, offset nume
      cmp  ax, numePointer
      jnb  invalidIndex
      mov  di, ax
      lea  si, [di + 6]
      mov  cx, numePointer
      sub  cx, si
      cld
      rep movsb
      mov  numePointer, di
      dec  numes
      jmp  bucla
    
      ...
    

    Beware of this: after deletion of a name you will probably want to use lista again. Make sure you reset the numeIndex to "1". Otherwise my code from I have an indexing problems won't function as it should:

    lista:
      mov  byte ptr [numeIndex + 2], "1"
      ...