Loop and decrease counter not working - assembly - loops

I am new to assembly language and was asked to have a program that will allow only three chances of error when typing the password in.
s:
main proc
mov ax, #data
mov ds, ax
mov cx, 3
again:
mov ah, 9
lea dx, a
int 21h
mov ah, 2
mov dl, '*'
int 21h
mov ah, 8
int 21h
mov bl, al
mov ah, 2
cmp bl, 'Y'
je second
cmp bl, 'y'
je second
jne iinvalid
second:
mov ah, 2
mov dl, '*'
int 21h
mov ah, 8
int 21h
mov bh, al
mov ah, 2
cmp bh, 'E'
je third
cmp bh, 'e'
je third
jne iinvalid
third:
mov ah, 2
mov dl, '*'
int 21h
mov ah, 8
int 21h
mov cl, al
mov ah, 2
cmp cl, 'S'
je welcome
cmp cl, 's'
je welcome
jne iinvalid
iinvalid:
jmp invalid
checking:
mov ah, 9
lea dx, i
int 21h
jmp exit
togo:
loop again
welcome:
mov ah,9
lea dx, c
int 21h
lea dx, d
int 21h
mov ah, 1
int 21h
mov bl, al
newp:
mov ah, 9
lea dx, i
int 21h
jmp exit
invalid:
mov ah, 9
lea dx, b
int 21h
mov ah, 1
int 21h
mov cl, al
cmp cl, 'Y'
je togo
cmp cl, 'y'
je togo
jne exit
exit:
mov ah, 4ch
int 21h
main endp
end s

you destroy the content of cx inside the loop.
easiest way to fix it:
mov cx, 3
again:
push cx ; save loop cnt on stack
mov ah, 9
...
togo:
pop cx ; restore cnt from stack
loop again
keep in mind, that if you jump out of the loop, cx must still be removed from stack
welcome:
pop cx ; purge cnt from stack
mov ah,9
just a hint:
you compare the characters entered, to be either lowercase, or uppercase
uppercase and lowercase characters are (in ascii) identically, except of bit 0x20. you could "mask out" this bit by an AND with 0xDF ( 1101 1111 binary), and check the characters with just a single branch (instead of 3):
cmp bl, 'Y'
je second
cmp bl, 'y'
je second
jne iinvalid
--->
and bl, 0xdf ; make lowercase to uppercase
cmp bl, 'Y' ; THEN here both 'y' and 'Y' match
jne iinvalid

Related

What is the flowchart corresponding to the "add-sub" program emu8086?

name "add-sub"
org 100h
mov al, 5 ; bin=00000101b
mov bl, 10 ; hex=0ah or bin=00001010b
add bl, al
sub bl, 1
mov cx, 8
print: mov ah, 2 ; print function.
mov dl, '0'
test bl, 10000000b ; test first bit.
jz zero
mov dl, '1'
zero: int 21h
shl bl, 1
loop print
mov dl, 'b'
int 21h
mov ah, 0
int 16h
ret

I got stuck at "Enter a string:" and doesn't take any input-8086 programming

In the program for to find out no. of vowels in a string. I got stuck at "Enter a string:" ?? why? even tho the compiler says everything okay.
program to count the no. of vowels in a string.
;;;;;;;PROGRAM TO CHECK NO. OF VOWELS IN A STRING;;;;;
.model small
.stack 100h
.data
vowels db 'AEIOUaeiou$'
msg1 db 'Enter a string:$'
msg2 db 'The string is:$'
msg3 db 'No of vowels are:$'
string db 50 dup('$')
count db ?
.code
main proc
mov ax, #data
mov ds, ax
mov es, ax
lea dx,msg1
mov ah,09h ;for displaying enter a string
int 21h
lea di,string
cld
xor bl,bl
input:mov ah,01 ; stuck here, at taking input, why??
cmp al, 13
je endinput
stosb
inc bl
jmp input
endinput:cld
xor bh,bh
lea si,string
vowelornot: mov cx,11
lodsb
lea di,vowels
repne scasb
cmp cx, 00
je stepdown
inc bh
stepdown: dec bl
jnz vowelornot
mov ah,06 ;;;THIS FOR CLEARING SCREEN I GUESS
mov al,0 ;;;
int 10h
lea dx,msg2
mov ah,09
int 21h
mov dl, 13 ;;; NEW LINE
mov ah, 2
int 21h
mov dl, 10
mov ah, 2
int 21h
lea dx,string
mov ah, 09
int 21h
mov dl,13 ;;;NEW LINE
mov ah,2
int 21h
mov dl,10
mov ah,2
int 21h
lea dx, msg3
mov ah,09
int 21h
mov dl,13 ;;;NEW LINE
mov ah,2
int 21h
mov dl,10
mov ah,2
int 21h
mov count, bh
mov dh, count ;;; DH = VOWEL COUNT
mov ah,09
int 21h
mov ah, 4ch ;;; EXIT
int 21h
main endp
end
Multiple errors
input:mov ah,01 ; stuck here, at taking input, why??
cmp al, 13
Here your code is missing the int 21h instruction!
input:
mov ah,01
int 21h
cmp al, 13
xor bl,bl
input:
stosb
inc bl
jmp input
You're using BL to count the number of characters in the input string but the example you wrote needs much more than the 255 maximum that this byte-sized register can give you. This must fail!
Moreover the buffer that you've setup is limited to 50 bytes. No way you could store there such a long input.
lea si,string
vowelornot: mov cx,11
lodsb
lea di,vowels
repne scasb
cmp cx, 00
je stepdown
inc bh
stepdown: dec bl
jnz vowelornot
This is too complicated. Just interpret the ZeroFlag and don't look at CX at all. You don't need to terminate the vowels text with a "$" anymore (use CX=10).
lea si,string
vowelornot:
lodsb
mov cx,10
lea di,vowels
repne scasb
jne stepdown
inc bh ;Vowel found +1
stepdown:
dec bl
jnz vowelornot
mov ah,06 ;;;THIS FOR CLEARING SCREEN I GUESS
mov al,0 ;;;
int 10h
Sure, function 06h can clear the screen but you need to provide all of the required arguments. Upperleftcorner in CX, Lowerrightcorner in DX and Displaypage in BH.
mov dx, 184Fh ;(79,24) If screen is 80x25
xor cx, cx ;(0,0)
mov bh, 0
mov ax, 0600h
int 10h
lea dx,string
mov ah, 09
int 21h
This will fail because you did not put a "$" character at the end of the inputted string.
And if you're going to output a CRLF directly afterwards, why not add it to the buffer?
jmp input
endinput:
mov ax, 0A0Dh <-- ADD THIS
stosw <-- ADD THIS
mov al, "$" <-- ADD THIS
stosb <-- ADD THIS
xor bh,bh
You print msg2 and msg3 followed by a CRLF. Why don't you append it in the definition? No more need to output it separately.
msg2 db 'The string is:', 13, 10, '$'
msg3 db 'No of vowels are:', 13, 10, '$'
mov count, bh
mov dh, count ;;; DH = VOWEL COUNT
mov ah,09
int 21h
To output the count and provided it is a number in the range from 0 to 9, you need to convert the number into a character. Just add 48 or '0'.
Don't use function 09h. It requires an address and you clearly want to use a character.
mov dl, bh ;Count of vowels [0,9]
add dl, '0'
mov ah, 02h
int 21h

FASM: How to input values in array using loop

This code doesn't work for me. My goal is to ask user string input, convert to capital letters, and store them one by one in an array, then output the characters(that is in all caps) back to the user. please help me :(
org 100h
mov bl, 0
mov ah, 9
mov dx, input
int 21h
again:
mov ah, 1
int 21h
sub al, 20h
mov [inp+bl], al
inc bl
cmp bl, 2
jle again
loops:
mov bl, 0
mov ah, 2
mov dl, [inp+bl]
int 21h
inc bl
cmp bl, 2
jle loops
mov ax, 4Ch
int 21h
input db 'Input: ',24h
output db 'Output: ',24h
inp db 20 dup(?), 24h
mov [inp+bl], al
The main problem here is that you use an addressing mode that simply does not exist!
You can quickly correct your code if you change every instance of BL into BX.
mov bx, 0
mov ah, 9
mov dx, input
int 21h
again:
mov ah, 1
int 21h
sub al, 20h
mov [inp+bx], al
inc bx
cmp bx, 2
jle again
loops:
mov bx, 0
mov ah, 2
mov dl, [inp+bx]
int 21h
inc bx
cmp bx, 2
jle loops
sub al, 20h
Perhaps you've over-simplified the code because this capitalization will of course only work if the user only types in small caps a..z and nothing else.

Assembler MASM, printing in JNZ loop when value is 0 or below

I'v got a a task to write a program which would create below as output:
ABCD******
ABCD***
ABCD
My code is:
kod segment
org 100h
assume cs:kod
start:
mov cx,3
mov bx,3
mov ax,6
mov ah, 02h
PETLA_ZEW:
push cx
mov cx,4
mov dl, 'A'
PETLA_CIAG:
int 21h
inc dl
dec cx
jnz PETLA_CIAG
push ax
mov cx, ax
mov dl, '*'
PETLA_GWIAZD:
int 21h
dec cx
jnz PETLA_GWIAZD
sub ax, 3
mov dl, 0ah
int 21h
mov dl, 0dh
int 21h
push bx
mov cx, bx
mov dl, ' '
PETLA_SPACJE:
int 21h
dec bx
jnz PETLA_SPACJE
pop bx
add bx, 3
pop cx
dec cx
jnz PETLA_ZEW
koniec:
mov ah, 4ch
int 21h
kod ends
end start
but the problem is that in loop called PETLA_GWIAZD when I subtract ax 2nd time it's value is 0, which is causing the infinite loop. Is there any other loop I should use when subtracting? Maybe some validation check just before the loop? I just started working with Assembly and still do not know a lot...
Thanks!
The problem is the registers you are using : AX and CX are used for interrupts and loops, so you can use other registers, for example, SI instead of CX and DI instead of AX :
kod segment
org 100h
assume cs:kod
start:
mov si,3 ;◄■■ INSTEAD OF CX.
mov bx,3
mov di,6 ;◄■■ INSTEAD OF AX.
mov ah, 02h
PETLA_ZEW:
mov cx,4
mov dl, 'A'
PETLA_CIAG:
int 21h
inc dl
dec cx
jnz PETLA_CIAG
cmp di, 0 ;◄■■ IF COUNTER == 0 ...
je koniec ;◄■■ ... NO MORE ASTERISKS.
mov cx, di ;◄■■
mov dl, '*'
PETLA_GWIAZD:
int 21h
dec cx
jnz PETLA_GWIAZD
sub di, 3 ;◄■■
mov dl, 0ah
int 21h
mov dl, 0dh
int 21h
push bx
mov cx, bx
mov dl, '_'
PETLA_SPACJE:
int 21h
dec bx
jnz PETLA_SPACJE
pop bx
add bx, 3
dec si ;◄■■
jnz PETLA_ZEW
koniec:
mov ah, 4ch
int 21h
kod ends
end start

Pass array as parameter to proc in TASM?

I'm trying to create a proc in TASM that accepts arrays as parameters. Problem is, the result is all messed up. This is the code:
TextParameter equ [bp+8]
MenuColorParameter equ [bp+6]
RowToPrint equ [bp+4]
PrintBar proc
push bp
mov bp, sp
mov dh, RowToPrint
mov dl, 0
mov bh, 0
mov ah, 2
int 10h
mov si, 0
mov cx, 1
##Print:
mov ah, 9
mov al, [TextParameter+si]
mov bl, [MenuColorParameter+si]
int 10h
mov ah, 2
inc dl
int 10h
inc si
cmp si, MENU_LEN ; const in DATASEG
jc ##Print
mov ah, 2
mov bh, 0
mov dl, 0
mov dh, 2
int 10h
pop bp
ret 6
PrintBar endp
When referencing the array through the DATASEG (as in mov al, Array[si]), the proc works as expected.
I'm assuming that you're passing the arrays by-address (i.e. their offsets), since the arguments seem to be 2 bytes each. If so, you need to first load that address into a register, and then add si and do another read from memory:
mov bx, TextParameter ; expands to mov bx,[bp+8]
mov al, [bx+si]
mov bx, MenuColorParameter ; expands to mov bx,[bp+6]
mov bl, [bx+si]
In addition to Michael's answer, I found the problem - int 10h ah=9 and int 10h ah=2 expect bh as the video page number. After assigning al and bl, I needed to mov bh, 0. The ##Print label is now this:
##Print:
mov ah, 9
mov bx, TextParameter
mov al, [bx+si]
mov bx, MenuColorParameter
mov bl, [bx+si]
mov bh, 0
int 10h
mov ah, 2
inc dl
int 10h
inc si
cmp si, MENU_LEN ; const in DATASEG
jc ##Print

Resources