I am trying to make a 8086 program in which I input an array of string and then the program prints them. But the program prints only the 1st characters of input strings and jumbled text.
This is the code where I attempted to do it.
data segment
; Definicija podataka
poruka1 DB "Input array length: $"
strN DB " "
N DW 0
poruka2 DB "Input string: $"
strM DB " "
niz1 DB 16 dup(?)
ends
; Deficija stek segmenta
stek segment stack
dw 128 dup(0)
ends
; Ucitavanje znaka bez prikaza i cuvanja
keypress macro
push ax
mov ah, 08
int 21h
pop ax
endm
; Isis stringa na ekran
writeString macro s
push ax
push dx
mov dx, offset s
mov ah, 09
int 21h
pop dx
pop ax
endm
; Kraj programa
krajPrograma macro
mov ax, 4c02h
int 21h
endm
code segment
; Novi red
novired proc
push ax
push bx
push cx
push dx
mov ah,03
mov bh,0
int 10h
inc dh
mov dl,0
mov ah,02
int 10h
pop dx
pop cx
pop bx
pop ax
ret
novired endp
; Ucitavanje stringa sa tastature
; Adresa stringa je parametar na steku
readString proc
push ax
push bx
push cx
push dx
push si
mov bp, sp
mov dx, [bp+12]
mov bx, dx
mov ax, [bp+14]
mov byte [bx] ,al
mov ah, 0Ah
int 21h
mov si, dx
mov cl, [si+1]
mov ch, 0
kopiraj:
mov al, [si+2]
mov [si], al
inc si
loop kopiraj
mov [si], '$'
pop si
pop dx
pop cx
pop bx
pop ax
ret 4
readString endp
; Konvertuje string u broj
strtoint proc
push ax
push bx
push cx
push dx
push si
mov bp, sp
mov bx, [bp+14]
mov ax, 0
mov cx, 0
mov si, 10
petlja1:
mov cl, [bx]
cmp cl, '$'
je kraj1
mul si
sub cx, 48
add ax, cx
inc bx
jmp petlja1
kraj1:
mov bx, [bp+12]
mov [bx], ax
pop si
pop dx
pop cx
pop bx
pop ax
ret 4
strtoint endp
; Konvertuje broj u string
inttostr proc
push ax
push bx
push cx
push dx
push si
mov bp, sp
mov ax, [bp+14]
mov dl, '$'
push dx
mov si, 10
petlja2:
mov dx, 0
div si
add dx, 48
push dx
cmp ax, 0
jne petlja2
mov bx, [bp+12]
petlja2a:
pop dx
mov [bx], dl
inc bx
cmp dl, '$'
jne petlja2a
pop si
pop dx
pop cx
pop bx
pop ax
ret 4
inttostr endp
start:
; postavljanje segmentnih registara
ASSUME cs: code, ss:stek
mov ax, data
mov ds, ax
; Mesto za kod studenata
writeString poruka1
; Unos broja elemenata
push 3
push offset strN
call readString
; Pretvaranje strN u broj
push offset strN
push offset N
call strtoint
call novired
writeString strN
; Unos elemenata niza
mov cx, N
mov di, 0
mov si, 0
unos:
call novired
writeString poruka2
push 6
push offset strM
call readString
mov al, strM
mov niz1[di], al
add di, 2
add si, 1
loop unos
call novired
mov cx, N
mov di, 0
mov si, 0
ispis:
writeString niz1[di]
add di, 2
add si, 1
loop ispis
krajPrograma
ends
end start
I input an array of string and then the program prints them. But the program prints only the 1st characters of input strings ...
What else could the program print if the 1st character is all that you store in memory?
mov al, strM
mov niz1[di], al
add di, 2
... and jumbled text.
With add di, 2 you leave an undetermined byte between any two of these 1st characters. That's not going to look nice. Make that byte the DOS string terminator $.
Your writeString macro does not load an address but a word from memory. That's not going to work. The invokation writeString niz1[di] gets expanded into mov dx, offset niz1[di]. What you need here is LEA instead of MOV.
Try the following:
....
unos:
call novired
writeString poruka2
push 6
push offset strM
call readString
mov al, strM
MOV AH, "$"
mov niz1[di], AX
add di, 2
loop unos
call novired
mov cx, N
mov di, 0
ispis:
LEA DX, niz1[di]
MOV AH, 09h
INT 21h
add di, 2
loop ispis
...
I have these 3 .asm files and 1 c file.
Exp3_1.asm
NAME MAIN
.386
.MODEL FLAT, C
printf PROTO :ptr sbyte, :VARARG
scanf PROTO :ptr sbyte, :VARARG
includelib libcmt.lib
includelib legacy_stdio_definitions.lib
;DATA SEGMENT USE16 PARA PUBLIC 'DATA'
CRLF MACRO ;�س�
invoke printf, offset FMT, addr CRLFT
ENDM
PRINT MACRO A ;��ӡ����
invoke printf, offset FMT, addr A
ENDM
READ MACRO A ;��ȡ����
invoke scanf, offset FMT, addr A
ENDM
SHOWVALUE MACRO A, B
PRINT A
MOV AX, B[EBX]
LEA ESI, VALUE
CALL F2TO10
MOV BYTE PTR [ESI], 0DH
MOV BYTE PTR [ESI+1], 0AH
MOV BYTE PTR [ESI+2], 0
PRINT VALUE
ENDM
CHANGEVALUE MACRO A, B
LOCAL LL
LL: PRINT A
MOV AX, B[EBX]
LEA ESI, VALUE
CALL F2TO10
MOV BYTE PTR [ESI], 0
PRINT VALUE
PRINT SEPARATOR
CALL GETVALUE
CMP DI, 1
JE LL
MOV B[EBX], DX
ENDM
.DATA
MENUT DB 'Please Enter a Number(1~9):', 0
INNAMET DB 'User Name:', 0
WRONGNAMET DB 'Invalid User Name', 0
INNAME DB 10 DUP(0)
INPWDT DB 'Password:', 0
WRONGPWDT DB 'Invalid Password', 0
INPWD DB 10 DUP(0)
LOGINST DB 'Login in', 0
INGOODT DB 'Good Name:', 0
WRONGGOODT DB 'Invalid Good Name', 0
INGOOD DB 10 DUP(0)
CHANGEGOODT DB 'Good Selected', 0
NOGOODT DB 'No Goods', 0
SELLGOODT DB 'Good Sold', 0
NOTSELECTEDT DB 'No Goods Selected', 0
UPDATEPRIOT DB 'Priority Updated', 0
NOTBOSST DB 'Authrity Denied', 0
BPRICET DB 'Buying Price:', 0
SPRICET DB 'Selling Price:', 0
BAMOUNTT DB 'Buying Amount:', 0
SAMOUNTT DB 'Selling Amount:', 0
VALUE DB 8 DUP(0)
SEPARATOR DB '->',0
BNAME DB 'GUSHIYU', 0 ;�ϰ�����
BPASS DB '153426', 0 ;����
AUTH DB 0 ;��ǰ��¼״̬��0��ʾ�˿�״̬
GOOD DD 0 ;��ǰ�����Ʒ��ַ
N EQU 30
SNAME DB 'SHOP', 0 ;�������ƣ���0����
GA1 DB 'PEN', 7 DUP(0), 10 ;��Ʒ���Ƽ��ۿ�
DW 35, 56, 70, 25, ? ;�����ۣ����ۼۣ����������������������Ƽ���
GA2 DB 'BOOK', 6 DUP(0), 9 ;��Ʒ���Ƽ��ۿ�
DW 12, 30, 25, 5, ? ;�Ƽ��Ȼ�δ����
GAN DB N-2 DUP( 'TempValue' , 0, 8, 15, 0, 20, 0, 30, 0, 2, 0, ?, ?)
;������ƷĬ��ֵ
CRLFT DB 0DH, 0AH, 0
A DB 'A', 0 ;������
B DB 'B', 0
FMT DB '%s', 0
FMTC DB '%c', 0
CHAR DB 0
.CODE
;START: MOV AX, DATA ;����ʼ
;MOV DS, AX
;MENU: PRINT MENUT ;���˵�
;MOV AH, 01H
;INT 21H
;CRLF
;CMP AL, '1'
;JE CF1
;CMP AL, '2'
;JE CF2
;CMP AL, '3'
;JE CF3
;CMP AL, '4'
;JE CF4
;CMP AL, '6'
;JE CF6
;CMP AL, '8'
;JE CF8
;CMP AL, '9'
;JE OVER
;JMP MENU
;CF1: CALL FUNC1
;JMP MENU
;CF2: CALL FUNC2
;JMP MENU
;CF3: CALL FUNC3
;JMP MENU
;CF4: CALL FUNC4
;JMP MENU
;CF6: CALL FUNC6
;JMP MENU
;CF8: CALL FUNC8
;JMP MENU
FUNC1 PROC ;����1
;LOCAL CHECK_USER, CHECK_PWD, WRONG_NAME, WRONG_PWD, LOGIN_S
PRINT INNAMET
READ INNAME
CRLF
LEA EDI, INNAME
LEA ESI, BNAME
CHECK_USER: ;���ֽڱȽ��û���
MOV AL, [EDI]
CMP AL, [ESI]
JNE WRONG_NAME
INC EDI
INC ESI
CMP AL, 0
JNZ CHECK_USER
PRINT INPWDT
READ INPWD
CRLF
LEA EDI, INPWD
LEA ESI, BPASS
CHECK_PWD: ;���ֽڱȽ�����
MOV AL, [EDI]
CMP AL, [ESI]
JNE WRONG_PWD
INC EDI
INC ESI
CMP AL, 0
JNZ CHECK_PWD
JMP LOGIN_S
WRONG_NAME:
PRINT WRONGNAMET
CRLF
RET
WRONG_PWD:
PRINT WRONGPWDT
CRLF
RET
LOGIN_S: ;��½�ɹ�
MOV AUTH, 1
PRINT LOGINST
CRLF
RET
FUNC1 ENDP
FUNC2 PROC ;����2
;LOCAL CHECK_GOOD, CHECK_NAME, WRONG_GOOD, CHANGE_GOOD
PRINT INGOODT
READ INGOOD
CRLF
MOV EAX, -1
CHECK_GOOD: ;ѡ����һ���Ƚ���Ʒ
INC EAX
CMP EAX, 30
JE WRONG_GOOD
MOV ECX, EAX
IMUL ECX, 21
ADD ECX, OFFSET GA1
MOV ESI, ECX
LEA EDI, INGOOD
CHECK_NAME: ;�Ƚ���Ʒ��
MOV BL, [EDI]
CMP BL, [ESI]
JNE CHECK_GOOD
INC EDI
INC ESI
CMP BL, 0
JNZ CHECK_NAME
JMP CHANGE_GOOD
WRONG_GOOD:
PRINT WRONGGOODT
CRLF
RET
CHANGE_GOOD: ;����ѡ����Ʒ
MOV EBX, EAX
IMUL EBX, 21
ADD EBX, OFFSET GA1
MOV GOOD, EBX
PRINT CHANGEGOODT
CRLF
SHOWVALUE BPRICET, 11
SHOWVALUE SPRICET, 13
SHOWVALUE BAMOUNTT, 15
SHOWVALUE SAMOUNTT, 17
RET
FUNC2 ENDP
FUNC3 PROC ;����3
MOV EBX, GOOD
CMP EBX, 0
JE NO_SELECTED
MOV AX, 15[EBX]
MOV DX, 17[EBX]
CMP AX, DX
JNE SELL_GOOD
PRINT NOGOODT
CRLF
RET
SELL_GOOD:
INC DX
MOV 17[EBX], DX
PRINT SELLGOODT
CRLF
CALL FUNC4
RET
NO_SELECTED:
PRINT NOTSELECTEDT
CRLF
RET
FUNC3 ENDP
FUNC4 PROC ;����4
;LOCAL COMPUTE_PRIO, COMPUTE_OVER
PUSH EBP
MOV EBP, -1
PRINT UPDATEPRIOT
CRLF
COMPUTE_PRIO:
INC EBP
CMP EBP, 30
JE COMPUTE_OVER
LEA ESI, GA1
MOV ECX, EBP
IMUL ECX, 21
ADD ESI, ECX
MOV EBX, ESI
ADD EBX, 13
MOV AX, [EBX-2]
MOV BX, [EBX]
MOVSX EAX, AX
MOVSX EBX, BX
MOV EDI, 128
IMUL EDI
IDIV EBX
MOV ECX, EAX
MOV EBX, ESI
ADD EBX, 15
MOV AX, [EBX+2]
MOV BX, [EBX]
MOVSX EAX, AX
MOVSX EBX, BX
IMUL EDI
MOV EDI, 2
IDIV EDI
MOV EDX, 0
IDIV EBX
ADD EAX, ECX
MOV EBX, ESI
ADD EBX, 19
MOV [EBX], AX
JMP COMPUTE_PRIO
COMPUTE_OVER:
POP EBP
RET
FUNC4 ENDP
FUNC8 PROC ;����8
;LOCAL GET_LETTER, IS_NUM, SHOW_OVER
PUSH BP
MOV BP, 4
MOV BX, CS
GET_LETTER:
MOV CL, 4;
ROL BX, CL
MOV DL, BL
AND DL, 0FH
CMP DL, 0AH
JB IS_NUM
ADD DL, 07H
IS_NUM: ADD DL, 30H
invoke printf, offset FMTC, DL
DEC BP
JZ SHOW_OVER
JMP GET_LETTER
SHOW_OVER:
CRLF
POP BP
RET
FUNC8 ENDP
F2TO10 PROC
PUSH BX
PUSH CX
PUSH DX
MOV BX, 10
XOR CX, CX
LOP1: XOR DX, DX
DIV BX
PUSH DX
INC CX
OR EAX, EAX
JNZ LOP1
LOP2: POP AX
CMP AL, 10
JB L1
ADD AL, 7
L1: ADD AL, 30H
MOV [ESI], AL
INC ESI
DEC CX
JNZ LOP2
POP DX
POP CX
POP BX
RET
F2TO10 ENDP
FUNC6 PROC
CMP AUTH, 0
JE NOT_BOSS
CMP GOOD, 0
JE NOT_SELECTED
MOV EBX, GOOD
CHANGEVALUE BPRICET, 11
CHANGEVALUE SPRICET, 13
CHANGEVALUE BAMOUNTT, 15
CHANGEVALUE SAMOUNTT, 17
RET
NOT_SELECTED:
PRINT NOTSELECTEDT
CRLF
RET
NOT_BOSS:
PRINT NOTBOSST
CRLF
RET
FUNC6 ENDP
GETVALUE PROC
PUSH AX
PUSH CX
XOR DI, DI
XOR CX, CX
XOR DL, DL
PUSH DX
LOOP1: invoke scanf, offset FMTC, ADDR CHAR
POP DX
MOV AL, CHAR
CMP AL, 0DH
JE RETURN
CMP AL, 0AH
JE RETURN
CMP AL, '0'
JB ERR
CMP AL, '9'
JA ERR
SUB AL, '0'
MOV CL, AL
MOV AX, DX
MOV DX, 10
MUL DX
ADD AX, CX
MOV AH, 0
MOV DX, AX
PUSH DX
JMP LOOP1
ERR: CRLF
MOV DI, 1
POP CX
POP AX
RET
RETURN: POP CX
POP AX
RET
GETVALUE ENDP
END
;END START
func6.asm
NAME FUNC6
PUBLIC FUNC6
EXTERN F2TO10:NEAR, NOTSELECTEDT:BYTE, NOTBOSST:BYTE, BPRICET:BYTE, SPRICET:BYTE, BAMOUNTT:BYTE, SAMOUNTT:BYTE, VALUE:BYTE, SEPARATOR:BYTE, AUTH:BYTE, GOOD:WORD, CRLFT:BYTE
PRINT MACRO A
LEA DX, A
MOV AH, 09H
INT 21H
ENDM
CRLF MACRO
LEA DX, CRLFT
MOV AH, 09H
INT 21H
ENDM
CHANGEVALUE MACRO A, B
LOCAL C
C: PRINT A
MOV AX, B[BX]
LEA SI, VALUE
CALL F2TO10
MOV BYTE PTR [SI], '$'
PRINT VALUE
PRINT SEPARATOR
CALL GETVALUE
CMP DI, 1
JE C
MOV B[BX], DX
ENDM
CODE SEGMENT USE16 PARA PUBLIC 'CODE'
ASSUME CS:CODE
FUNC6 PROC
CMP AUTH, 0
JE NOT_BOSS
CMP GOOD, 0
JE NOT_SELECTED
MOV BX, GOOD
CHANGEVALUE BPRICET, 11
CHANGEVALUE SPRICET, 13
CHANGEVALUE BAMOUNTT, 15
CHANGEVALUE SAMOUNTT, 17
RET
NOT_SELECTED:
PRINT NOTSELECTEDT
CRLF
RET
NOT_BOSS:
PRINT NOTBOSST
CRLF
RET
FUNC6 ENDP
GETVALUE PROC
PUSH AX
PUSH CX
XOR DI, DI
XOR CX, CX
XOR DX, DX
LOOP1: MOV AH, 01H
INT 21H
CMP AL, 0DH
JE RETURN
CMP AL, 0AH
JE RETURN
CMP AL, '0'
JB ERR
CMP AL, '9'
JA ERR
SUB AL, '0'
MOV CL, AL
MOV AX, DX
MOV DX, 10
MUL DX
ADD AX, CX
MOV DX, AX
JMP LOOP1
ERR: CRLF
MOV DI, 1
POP CX
POP AX
RET
RETURN: POP CX
POP AX
RET
GETVALUE ENDP
CODE ENDS
END
F2TO10.asm
NAME F2TO10
PUBLIC F2TO10
.386
CODE SEGMENT USE16 PARA PUBLIC 'CODE'
ASSUME CS:CODE
F2TO10 PROC
PUSH BX
PUSH CX
PUSH DX
MOV BX, 10
XOR CX, CX
LOP1: XOR DX, DX
DIV BX
PUSH DX
INC CX
OR EAX, EAX
JNZ LOP1
LOP2: POP AX
CMP AL, 10
JB L1
ADD AL, 7
L1: ADD AL, 30H
MOV [SI], AL
INC SI
LOOP LOP2
POP DX
POP CX
POP BX
RET
F2TO10 ENDP
CODE ENDS
END
main.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
extern void FUNC1();
extern void FUNC2();
extern void FUNC3();
extern void FUNC4();
extern void FUNC6();
extern void FUNC8();
int main()
{
int op = 0;
while (op != 9)
{
printf("SHOP:MY SHOP\n");
printf("---------------------------------------------\n");
printf("1.Login in\n2.Select good\n3.Buy good\n4.Update recommendation\n6.Update good\n8.Show CS\n9.Exit\n");
printf("---------------------------------------------\n");
printf("Please Enter a Number:");
scanf("%d", &op);
printf("*********************************************\n");
switch (op)
{
case 1:
FUNC1();
break;
case 2:
FUNC2();
break;
case 3:
FUNC3();
break;
case 4:
FUNC4();
break;
case 6:
getchar();
FUNC6();
break;
case 8:
FUNC8();
break;
default:
break;
}
printf("*********************************************\n");
system("pause");
system(("cls"));
}
return 0;
}
I am creating the project using visual studio 2019 and masm32 as include path. When trying to compile and create object files, there are no errors, but when it is a time to link all .obj files, i get this error:
Error LNK1190 invalid fixup found, type 0x0001 Lab3 C:\Users\Blaise\source\repos\Lab3\FUNC6.obj
How can i solve this problem? is it because of older link.exe file? i am using link.exe version 5.12
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
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