Loosos
Loosos

Reputation: 85

Intel 8086 assembly code: reading from terminal

I need help with my task in assembly (Intel 8086 CPU). The task is:

A program to try reading from the terminal line by line: Read input from the terminal line by line with INT 21h AH=0x0a and find the minimum line length in bytes. The length does not include characters ending the line, i.e. you use the length passed by the service AH=0x0a in the second byte as an unsigned number. Attention, you are comparing unsigned numbers.
You put the resulting minimum length in the byte variable rsltbe in the data segment as an unsigned number.
Assume that at least one row will always be loaded.
Since the length is an unsigned byte number, a line up to a total length of 255 bytes may be processed.

I tried many times rewriting the code. Last time I tried this one, but it too doesn't work correctly:

cpu 8086
segment code
..start mov bx,data
    mov ds,bx
    mov bx,stack
    mov ss,bx
    mov sp,dno
    
    mov al,0
    
lop mov bl,[loaded+1]
    cmp al,bl
    jb change
back    mov AH, 0x0a
    mov DX, loaded
    int 21h
    jnz lop
    mov [rsltbe],al
    hlt
    
change  mov al,bl
    jmp back
    
segment data
rsltbe  db 0
loaded db 255,0
    resb 255
    
segment stack
    resb 16
dno:    db ?

Upvotes: 2

Views: 1061

Answers (1)

Sep Roland
Sep Roland

Reputation: 39166

Review

  • You tagged your question , but in emu8086 (that uses MASM-style), an instruction like mov DX, loaded will not load the address of the input structure in DX, but rather load a word from memory. That is not what you need. Nonetheless, DOS will perform an input and store the result somewhere else than what you expect.

  • The DOS.BufferedInput function 0Ah does not return any flags. Therefore acting on the zero flag (jnz lop) will produce unexpected results. And neither does this DOS function return any defined value in the AX register. Moreover, practice dictates that you should not trust any DOS function to even retain the pre-existing value from the AX register.

  • At 16 bytes, your stack is much too small to function correctly. Better make this something like 512 bytes.

  • Your current attempt interprets a length even before having performed a first input! The task description says "Assume that at least one row will always be loaded." So execute the input first.

Since the objective is to find the shortest line, initialize your reference variable CL with the maximum unsigned value which is 255. Then if the actual input is shorter than that, load the new value in the reference variable.

MASM-style

  ...
  mov  cl, 255               ; Reference variable
  mov  bx, OFFSET loaded + 1
Again:
  mov  byte ptr [bx], 0      ; Always a fresh input 
  lea  dx, [bx - 1]
  mov  ah, 0Ah               ; DOS.BufferedInput
  int  21h
  mov  al, [bx]              ; Actual length (excluding carriage return)
  cmp  al, 0
  je   Done                  ; Stop on an empty input
  cmp  al, cl
  jnb  Again                 ; This line is not shorter
  mov  cl, al
  jmp  Again                 ; This line is shortest up till now
Done:
  mov  rsltbe, cl            ; [1,254]
  ...

NASM-style

  ...
  mov  cl, 255               ; Reference variable
  mov  bx, loaded + 1
Again:
  mov  byte [bx], 0          ; Always a fresh input 
  lea  dx, [bx - 1]
  mov  ah, 0Ah               ; DOS.BufferedInput
  int  21h
  mov  al, [bx]              ; Actual length (excluding carriage return)
  cmp  al, 0
  je   Done                  ; Stop on an empty input
  cmp  al, cl
  jnb  Again                 ; This line is not shorter
  mov  cl, al
  jmp  Again                 ; This line is shortest up till now
Done:
  mov  [rsltbe], cl          ; [1,254]
  ...

Upvotes: 1

Related Questions