Input and print an array of strings in Assembly 8086 - arrays

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
...

Related

Subtraction of Two Arrays and Stores Result in 3rd array and display the result on screen in Assembly language 8086

I have already written the code to add TWO arrays and Store the result in 3rd array. But the problem occurs while handling the NEGATIVE SIGN Numbers to display with (-) sign. Follow are the code listed below while subtracting the 6th element of array1 with array 2, result is GARBAGE value Need assistance immediately. After running executing's the code, all signed values are not displaying correctly.
org 100h
Array1 db 1,3,2,2,2,2,2,2,2,2
Array2 db 4,5,6,7,8,9,0,1,2,3
Array3 db 10 dup (?)
lea dx, msg1
mov ah, 9
int 21h
mov cx, 10
mov bx, 0
L1001:
mov al, Array1 [bx]
; Extend (unsigned) AL to AX (to print)
mov ah, 0
call printd
mov ah, 2
mov dl, 09 ;TAB Character
int 21h
inc bx
loop L1001 ;End Loop1
mov ah,2
mov dl,10
int 21h
mov dl,13
int 21h
; print msg2
lea dx, msg2
mov ah, 9
int 21h
; Use loop to print values of Array2
mov cx, 10
mov bx, 0
L1002:
mov al, Array2 [bx]
; Extend (unsigned) AL to AX (to print)
mov ah, 0
call printd
mov ah, 2
mov dl, 09 ;TAB Character
int 21h
inc bx
loop L1002 End Loop2
mov ah,2
mov dl,10
int 21h
mov dl,13
int 21h
; print msg3
lea dx, msg3
mov ah, 9
int 21h
mov cx,10
mov bx, 0
L1003: ; Main Addition
mov al, Array1 [bx]
sub al, Array2 [bx]
mov Array3 [bx], al
; Extend (unsigned) AL to AX (to print)
mov ah, 0
call printd
mov ah, 2
mov dl, 09 ;TAB Character
int 21h
inc bx
loop L1003 ; End of lOOP3
lea dx, pkey
mov ah, 9
int 21h ; output string at ds:dx
; wait for any key....
mov ah, 1
int 21h
mov ax, 4c00h ; exit to operating system.
int 21h
printd proc
; preserve used registers
push ax
push bx
push cx
push dx
; if negative value, print - and call again with -value
cmp ax, 0
jge L1
mov bx, ax
; print -
mov dl, '-'
mov ah, 2
int 21h
; call with -AX
mov ax, bx
neg ax
call printd
jmp L3
L1:
; divide ax by 10
; ( (dx=0:)ax / cx(= 10) )
mov dx, 0
mov cx, 10
div cx
; if quotient is zero, then print remainder
cmp ax, 0
jne L2
add dl, '0'
mov ah, 2
int 21h
jmp L3
L2:
; if the quotient is not zero, we first call
; printd again for the quotient, and then we
; print the remainder.
; call printd for quotient:
call printd
; print the remainder
add dl, '0'
mov ah, 2
int 21h
L3:
; recover used registers
pop dx
pop cx
pop bx
pop ax
ret
printd endp
printud proc ;Print Undecimal Numbers
push ax
push bx
push cx
push dx
mov dx, 0
mov cx, 10
div cx
cmp ax, 0
jne L4
add dl, '0'
mov ah, 2
int 21h
jmp L5
L4:
call printud
add dl, '0'
mov ah, 2
int 21h
L5:
pop dx
pop cx
pop bx
pop ax
ret
printud endp ;
ret
msg1 db "Array 1 = $"
msg2 db "Array 2 = $"
msg3 db "Array 3 = : $"
pkey db "press any key...$"
mov al, Array1 [bx]
sub al, Array2 [bx]
mov Array3 [bx], al
; Extend (unsigned) AL to AX (to print)
mov ah, 0
call printd
You say that your program is having trouble displaying the negative numbers, but your code is never feeding any negative number to the printd routine! Whatever the signed result of the subtraction in AL may be, the mov ah, 0 that follows will produce a positive number in AX and it is AX that printd processes...
You should replace mov ah, 0 by cbw.
But, what is terribly wrong is the placement of the 3 arrays. They can't be at the top of the program like that. The cpu is executing their bytes (data) as if it were instructions (code)!
Move those 3 lines towards the bottom of the source.
It surprised me to see these recursive solutions to display a decimal number. I believe they are correct with one exception though! If you feed printd the negative number -32768 then the program will fall into an infinite loop. This happens because the negation of that particular value is again -32768.
You might want to investigate Displaying numbers with DOS for info about the iterative solution that is surely faster (and could be improved further by outputting the digits all at once).

Invalid fix up found,type 0x0001

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

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

How to print an array in DOS x86 assembly?

I have this code to copy the array "NUMBERS" to "DEST" such that no number will repeat (in this case it should be : 1,2,5,4,7)
The code works but now I need to print the array "DEST". How can I do that ?
data segment
NUMBERS db 1,2,1,1,1,5,5,4,7,7
DEST dt ?
data ends
code segment
assume ds:data, cs:code
start: mov ax, data
mov ds, ax
mov ax, 0a0ah
mov di, offset NUMBERS
mov bx, 0h
loop2:mov cl, [di]
mov si, offset DEST
mov ch, [si]
loop1:cmp ch, cl
je dontadd
inc si
mov ch, [si]
dec ah
jnz loop1
mov si, offset DEST
add si, bx
inc bx
mov [si], cl
dontadd:mov ah, 0ah
inc di
dec al
jnz loop2
mov ah, 4ch
int 21h
code ends
end start
You can use INT 21h, AH=02h to print a single character to STDOUT.
MOV CX,10
MOV SI,OFFSET DEST
print:
MOV DL,[si]
OR DL,DL
JE done
ADD DL,'0' ; <-- Convert numeric value in DL into ASCII code
MOV AH,02h
INT 21h
MOV DL,' ' ; Throw in a space to make things pretty
INT 21h
INC SI
LOOP print
done:
If elements in NUMBERS have values over 9 then you need more elaborate conversion of the numeric values into ASCII.
First convert numbers to string then print them.You can use this two macros for printing numbers:
printstr macro str
push ax
push dx
lea dx,str
mov ah,9
int 21h
pop dx
pop cx
endm
printnum macro n
local o,w,s,n5,lb1,lb2,lb3
pusha
push si
push di
jmp w
s db 7 dup('$')
w:
mov si,0
mov cx,7
o:mov s[si],'$'
inc si
loop o
mov si,0
xor ax,ax
mov ax,n
xor dx,dx
cmp ax,0
jge n5
mov bl,'-'
mov s[si],bl
inc si
neg ax
n5:mov cx,10
div cx
or dl,30h
mov s[si],dl
xor dx,dx
inc si
cmp ax,0
jne n5
mov si,0
cmp s[si],'-'
jne lb1
inc si
lb1:mov di,si
lb3:cmp s[si],'$'
je lb2
mov al,s[si]
push ax
inc si
jmp lb3
lb2:pop ax
mov s[di],al
inc di
cmp di,si
jl lb2
printstr s
pop di
pop si
popa
endm

Resources