Reputation: 85
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
Reputation: 39166
You tagged your question emu8086, 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.
...
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]
...
...
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