this is my code that supposed to sorting the array in the way that to find the smallest number but when I'm running that on the 8086 assembly I don't see any result or any thing else but I guess the problem is that my code cannot get out of the loop or something like that is that right?
again I'm saying that the problem on my code is that it doesn't show any result on the window and my program must find the second smallest number in the array.can someone help me to fix the it?
org 100h
; add your code here
DATA SEGMENT
ARR DB 5,3,7,1,9,2,6,8,4
LEN DW $-ARR
SMALL DB ?
SECOND DB ?
DATA ENDS
CODE SEGMENT
ASSUME DS:DATA CS:CODE
START:
MOV AX,DATA
MOV DS,AX
LEA SI,ARR
MOV AL,ARR[SI]
MOV SMALL,AL
MOV CX,LEN
REPEAT1:
MOV AL,ARR[SI]
CMP SMALL,AL
JL NOCHANGE
MOV SMALL,AL
NOCHANGE:
INC SI
LOOP REPEAT1
LEA SI,ARR
MOV AL,ARR[SI]
MOV SECOND,AL
MOV CX,LEN
REPEAT2:
MOV AL,ARR[SI]
CMP SECOND,AL
JL SKIP
CMP SMALL,AL
JGE SKIP
MOV SECOND,AL
SKIP:
INC SI
LOOP REPEAT2
MOV AH,4CH
INT 21H
CODE ENDS
END START
ret
I'm wondering at this point in your class if you are supposed to be able to output numbers as opposed to looking at register values while running a debugger.
As an alternative, insert the commented line into your code to return the value as an error code:
LOOP REPEAT2
MOV AH,4CH
MOV AL,SECOND ;insert this line
INT 21H
CODE ENDS
END START
After assembling and linking the program, run it from a DOS console window (Command prompt). Assume you named it "myprogram.com". Then use these commands:
myprogram
echo %errorlevel%
The errorlevel is the value in AL when using AH=4CH and INT 21H. This only works for single byte values, but that's what you have in this case.
Otherwise you would have to add code to convert the value to decimal and output the result. If these are singe digit values, then the output code is simple:
MOV DL,SECOND
ADD DL,030H
MOV AH,002H
INT 21H
MOV DL,00DH
MOV AH,002H
INT 21H
MOV DL,00AH
MOV AH,002H
INT 21H
or use a string:
SECOND DB ?
STRNG DB 000H,00DH,00AH,'$' ;insert this line
...
MOV AL,SECOND
ADD AL,30
MOV STRNG,AL
MOV DX,OFFSET STRNG
MOV AH,009H
INT 21H
Related
I'm experimenting with my program by trying to build different kinds of pyramids and converting the values into different values. I managed to build one with asterisk sign and now I'm trying to find a way on how to change it into running numbers like "0123456789" and the next line is "012345678" and so on. Is there a way to do that without fully/less changes of my code?
.MODEL SMALL
.STACK 100H
.DATA
STAR DB ?
BLANK DB ?
.CODE
MAIN PROC
MOV AX,#DATA
MOV DS,AX
MOV CX,10
MOV BH,10
MOV BL,0
MOV STAR,BH
MOV BLANK,BL
L1:
CMP BLANK,0
JE L2
MOV AH,2
MOV DL,32
INT 21H
DEC BLANK
JMP L1
L2:
MOV AH,2
MOV DL,'*'
INT 21H
DEC STAR
CMP STAR,0
JNE L2
MOV AH,2
MOV DL,0AH
INT 21H
MOV DL,0DH
INT 21H
DEC BH
MOV STAR,BH
INC BL
MOV BLANK,BL
LOOP L1
EXIT:
MOV AH,4CH
INT 21H
MAIN ENDP
END MAIN
I'm trying to find a way on how to change it into running numbers like "0123456789" and the next line is "012345678" and so on. Is there a way to do that without fully/less changes of my code?
While the other answer provides an alternative solution, my solution keeps most of your program intact as per request, only adding the digit sequence:
L2:
mov dl, '0' <--- Setup 1st digit
L3: <--- Extra label
MOV AH,2
INT 21H
inc dl <--- To next digit
DEC STAR
CMP STAR,0 ; Tip: you can remove this instruction
JNE L3 <--- To extra label
Expected output (similar to your asterisks):
0123456789
012345678
01234567
0123456
012345
01234
0123
012
01
0
Consider a simplier algorithm which uses DOS function Int 21h/AH=09h (which displays $-terminated strings). You may shorten the string by overwriting characters at its end with '$' in each loop cycle:
.MODEL SMALL
.STACK 100H
.DATA
EOL DB 13,10,'$' ; End of line string.
TXT DB '0123456789$' ; The initial string.
.CODE
MAIN PROC
MOV AX,#DATA
MOV DS,AX ; Initialize DS to .DATA segment.
MOV AH,9 ; Use DOS function WRITE STRING TO STANDARD OUTPUT.
MOV BX,10 ; Initialize the number of iteration (address index).
L1: MOV DX,OFFSET EOL
INT 21H ; Write EOL first.
MOV [TXT+BX],'$' ; Terminate TXT at index BX.
MOV DX,OFFSET TXT
INT 21H ; Write TXT.
DEC BX ; Let BX index the previous character.
JNZ L1 ; Loop while BX > 0.
EXIT:MOV AH,4CH
INT 21H
MAIN ENDP
END MAIN
Result should be this:
0123456789
012345678
01234567
0123456
012345
01234
0123
012
01
0
I want to print this array but also highlight specific characters from said array. This is my code:
include 'emu8086.inc'
.data
animales1 db 'BUBRPQYFODFZXIQ'
db 'MSVDJVQDTLOEATF'
db 'RCZPIFYGAZLPMFN'
db 'LVWKFFBKDXHFIUW'
db 'AOSEFQEMOOTGQUR'
db 'ELLWTGNJJKAJISJ'
db 'OVCOXLUEQTSDDSP'
db 'UEAEMTNYOLVYMGI'
db 'ORREPOMJZGYPHAI'
db 'IFTLCBJFVOYHLUB'
db 'WTOWZQFRAXQRLMR'
db 'KGNYIIHHHKFUKIJ'
db 'XMLSACGMVXEYSIT'
db 'TSOESQVSEQRFNPU'
db 'ODDQMDFWRGETDLY'
lenguajes2 db 'SLKFMBCULKVYUIM'
db 'TWCDQFYIVIKUXKB'
db 'GNIWEQBOSYEMDTJ'
db 'WDHFZZPUIEDERYQ'
db 'KMTGTKAKROMUSUV'
db 'BELBLLTUVJQHCRW'
db 'UPLUBYJKNUXORLF'
db 'SGMAOOEENBOGIWR'
db 'JVSTLPTEGPPNPJW'
db 'YINCASSEMBLYTTU'
db 'CHWTIOIWORDZDRV'
db 'BRZCNRAVRWAMUNU'
db 'KOMCOUKNGQEPQVS'
db 'XXRXJUJUBEXVGGA'
db 'MNKJQKZAACVCLDW'
char db 'a'
flag db 0
;Pez= 12,27,42
;Ave= 76,92,108
indx db 5,11,26,41,45 dup (' ')
.stack
.code
.start up
mov ax,0000h
mov bx,0000h
mov cx,0000h
mov dx,0000h
lea si, animales1
;call valueInArray
call printArrays
printArrays proc
mov bx,0000h
printArray:
mov dx,0000h
mov ah, 02h
mov dl,byte ptr[si+bx]
call valueinArray
cmp flag,1
jz printSpecial
int 21h
mov dl, 20h
int 21h
add bx, 1
add cl, 1
cmp cl,15
jz nextRow
jnz printArray
nextRow:
call nwLine
add ch,1
mov cl, 00h
cmp ch,15
jz finproc
jnz printArray
printSpecial:
lea di,char
mov byte ptr[di],dl
push ax
push bx
push cx
push dx
mov bp, offset char
mov dh,00h
mov al, 1
mov bh, 0
mov bl, 1111_0000b
mov cx, 1; calculate message size.
mov dx,0000h
mov ah, 13h
int 10h
mov dl, 20h
mov ah, 02h
int 21h
pop dx
pop cx
pop bx
pop ax
add bx, 1
add cl, 1
cmp cl,15
jz nextRow
jnz printArray
finproc:
ret
printArrays endp
nwLine PROC
MOV AH,02h
MOV DX,0Ah; imprime asscii 10 (nueva linea)
INT 21h
MOV DX,0Dh; imprime asscii 13 (retorno de carro)
INT 21h
RET
nwLine ENDP
valueInArray proc
mov flag, 0
mov di,0001h
iterar:
mov dh, indx[di]
cmp dh,20h
jz finvalueproc
cmp bl,dh
jz found
add di,1
jmp iterar
found:
mov flag,1
jmp finvalueproc:
finvalueproc:
ret
valueInArray endp
exit:
end
As you can see, the array 'indx' have the positions of the chars (The first number is the effective lenght of said array) that I want to highlight so I check if bx is in the position of said character to print it highlighted.
I have two problems at the moment, the first one is the highlighted characters are printing in a kinda random position and that messes up the rest, but I think I know why the position of the highlighted character that prints is wrong, because the interrupt that I use uses dh and dl as positioners but I do not know how to make it so it continues the flow of the rest. The second problem is that the character that prints is wrong, if you run it and check the variable char, it has an 'Z' but it prints a 'T'. I really need help. Pretty please. :(
indx db 5,11,26,41,45 dup (' ')
It could be that this line is not what you think it is!
Reading your explanation I think you really meant:
indx db 5, 11, 26, 41, 45, ' '
That is the length of the array which is 5, then followed by 4 offsets to the highlighted characters and 1 space character as a list terminator.
the first one is the highlighted characters are printing in a kinda random position and that messes up the rest, but I think I know why the position of the highlighted character that prints is wrong, because the interrupt that I use uses dh and dl as positioners but I do not know how to make it so it continues the flow of the rest.
Because your code to output the highlighted character uses mov dx,0000h, the BIOS function 13h places the character in the upperleft corner of the screen and the other, 'normal' characters will continue from there.
All you have to do is to ask BIOS where the cursor is at that moment using function 03h:
Replace
mov cx, 1; calculate message size.
mov dx,0000h
mov ah, 13h
int 10h
by
mov ah, 03h ; BIOS.GetCursorAndConfiguration
int 10h ; -> CX DX
mov cx, 1 ; message size
mov ah, 13h ; BIOS.WriteString
int 10h
Function 13h fetches from ES:BP. Did you setup the ES segment register?
The second problem is that the character that prints is wrong, if you run it and check the variable char, it has an 'Z' but it prints a 'T'.
Probably resolving the first problem will also resolve the second one.
There's a better, less convoluted way to output your highlighted character.
printSpecial:
push ax
push bx
push cx
mov cx, 1 ; ReplicationCount
mov bx, 00F0h ; DisplayPage 0, Attribute BlackOnBrightWhite (11110000b)
mov al, dl ; Character
mov ah, 09h ; BIOS.WriteCharacterAndAttribute
int 10h
mov ah, 0Eh ; BIOS.TeletypeCharacter
int 10h
pop cx
pop bx
pop ax
...
Function 09h will write your character with the colors that you need, and then function 0Eh will advance the cursor normally.
I managed to write this code for turbo debugger in assembly language which is meant to sort 10 integer numbers read from the keyboard and display them in ascending order but it keeps looping B to infinite..
The code is :
.model small
.stack 100h
.data
strg1 DB 'Insert numbers: $'
strg2 DB 'Sorted numbers: $'
Arr Db 10 dup(?)
v dw ?
.code
main proc
mov ax,#data
mov ds,ax
mov ah,9
lea dx,strg1
int 21h
mov dl,0ah
mov ah,2
int 21h
;inputs
mov di,0
mov cx,10
Input_loop:
mov ah,1
int 21h
mov arr[di],al
mov dl,0ah
mov ah,2
int 21h
inc di
loop Input_loop
mov v,0
sort:
mov di,0
mov cx,10
sub cx,v
B:
mov al,Arr[di]
cmp al,Arr[di+1]
jng C
mov al,Arr[di]
xchg al,Arr[di+1]
mov Arr[di],al
c:
inc di
loop B
inc v
cmp v,10
jne sort
;Output
mov ah,9
lea dx,strg2
int 21h
mov dl,0ah
mov ah,2
int 21h
mov di,0
mov cx,10
Output_loop:
mov dl,Arr[di]
mov ah,2
int 21h
inc di
mov dl,0ah
mov ah,2
int 21h
loop output_loop
mov ah,4ch
int 21h
main endp
end main
It is running perfectly, I can enter my desired numbers to be sorted, and then when it reaches c: , it just keeps looping B to infinite and it really makes me mad . Do you have any idea what went wrong and how can I fix it ?
Arr Db 10 dup(?)
v dw ?
In an array that has 10 elements, you can do 9 pairwise comparisons at most.
Your code does 10 comparisons and will move whatever byte is stored after the array, and that is probably a zero, down in memory!
Initialize v at 1:
mov v, 1
sort:
This is the only modification that I made and your program ran perfectly in DOSBox. I assembled the source using TASM 4.1 followed by TLINK
A better BubbleSort
Don't use BubbleSort, better algorithms exist! :-)=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Better use a register like SI instead of a memory based variable v.
Use downcounting for the outer loop count.
Because your elements are byte-sized, you can read and write two elements together.
Keep addressing modes simplest/shortest (using [di] instead of Arr[di]).
Avoid the slow LOOP instruction.
Use meaningful names for your labels.
Avoid using XCHG between a register and memory.
Use unsigned conditional jumps after comparing unsigned quantities like characters "0" to "9" (using jna instead of jng).
mov si, 10-1
Outer:
mov di, offset Arr
mov cx, si
Inner:
mov ax, [di]
cmp al, ah
jna Skip
xchg al, ah
mov [di], ax
Skip:
inc di
dec cx
jnz Inner
dec si
jnz Outer
I'm new to assembly language coding and there's this program I'm trying to work out where I initialize an array of letters (in ascii), loop through it, and print it to the console window as a concatenated string. This is what I have so far:
.MODEL flat
.DATA
name1 DB 4Ah, 69h, 6Dh, 6Dh, 79h
.CODE
main PROC
mov ecx, 0
mov esi, offset name1
loop1:
mov dl, [esi]
mov ah, 2
inc esi
inc ecx
cmp ecx, 5
jne loop1
endlp:
mov eax, 4c00h
ret
main ENDP
END
I'm pretty lost. Some of what I have here is from others trying to help me, so sorry if it looks messy.
Everything about your question cries DOS. I would suggest you use the tiny model for these simple demonstration programs.
In the 16-bit environment it's natural to use 16-bit registers.
To execute DOS api services you place the requested parameters in selected registers and store the function number in the AH register. Then you issue an int 21h call.
A more efficient loop will count downward. Often you can avoid the need to compare before looping back because the flags have been set by the dec instruction.
If you place the data of your program below the code that exits to DOS, you avoid mistakenly executing it.
You can write an array of ASCII codes easier as a string. See the 3rd example.
ORG 256 ;This asks for the tiny model
mov cx, 5
mov si, offset array
again:
mov dl, [si]
mov ah, 02h
int 21h ;Display character
inc si
dec cx
jnz again
mov ax, 4C00h
int 21h ;Exit the program
array db 4Ah, 69h, 6Dh, 6Dh, 79h
An alternative program doesn't use the CX counter at all. It suffices to stop when the pointer SI is pointing beyond the last character.
ORG 256 ;This asks for the tiny model
mov si, offset array
again:
mov dl, [si]
mov ah, 02h
int 21h ;Display character
inc si
cmp si, offset array+5
jb again
mov ax, 4C00h
int 21h ;Exit the program
array db 4Ah, 69h, 6Dh, 6Dh, 79h
Another alternative program uses a zero delimiter on the array. To see if the delimiter was reached, you can write cmp dl, 0 je exit but a bit better is to write test dl, dl jz exit.
ORG 256 ;This asks for the tiny model
mov si, offset array
again:
mov dl, [si]
test dl, dl ;Test for zero delimiter
jz exit
mov ah, 02h
int 21h ;Display character
inc si
jmp again
exit:
mov ax, 4C00h
int 21h ;Exit the program
array db 'Jimmy', 0
In this programm i struggle to convert string into number. I have spent around 10 hours with this code already (yeah, I'm a novice) and I have a strong feeling I'm so close to the point when it's gonna work... Please, prove me right or prove me wrong! =) I tried to add as many comments as possible in the most complicated (as for me) parts of the code so you can save your time in case you have a mood to help me out a little. I'll be glad to explaine code even more if neccessary. Sorry for my English and let's see the code.
model tiny
.code
org 0100h
start:
mov ax,cs
mov ds,ax
mov dx,offset text
mov ah,09h
int 21h
mov dx,offset x
mov ah,3fh
int 21h
mov dh,byte ptr[x+di] ; Loading first digit into elem.
sub dh,48
mov ah,2
CH2INT:mov elem,dh
_TEST: push di
OFFST1:mov cl,ah
dec cl
add di,di
loop OFFST1
mov dh,byte ptr[x+di] ; Loading next (x+di*2) digit into dh.
pop di ; Inc ah for the next iteration.
inc ah ; Here we see if next char is a digit or not,
cmp dh,"0" ; if it is (meaning that current digit isn't in the lowest position) -
jb INVAL ; multiplying current digit by 10 (our base),
cmp dh,"9" ; if not - jump to INVAL where we go on to the next digit (if there is any).
ja INVAL ; Push-pop ax just for convinience, I'm almost out of free-to-use registers.
push ax
mov al,elem
mov ten,10
imul ten
mov elem,al
pop ax
jmp _TEST
INVAL: mov al,elem ; Adding number we got to the sum which in the end (after jump to NEXT)
add sum,al ; will containe inputt size of array as a number, not a char.
push di
OFFST2:mov cl,ah
dec cl
add di,di
loop OFFST2
mov dh,byte ptr[x+di] ; Move next digit into dh (x+ah(wich was incremented earlier)+di).
pop di ; See if there is a next digit in x or previous one was the last one
cmp dh,"0" ; (I just hope that next value in memory after the inputt will not be a digit...
jb NEXT ; I understand that it's not nice and a luck game, but I do not yet come up with smthn better).
cmp dh,"9"
ja NEXT
push di ; Next few lines write next char into dh (but with index less by 1 than in previous
; few lines, where we checked is there any more digits in the inputt value left.
OFFST3:mov cl,ah
sub cl,2
add di,di
loop OFFST3
mov dh,byte ptr[x+di]
pop di
sub dh,48
jmp CH2INT ; Jump to next iteration to work with next digit in the inputt value
NEXT: mov dx,offset array
mov ah,3fh
int 21h
mov cl,sum
L: mov dh,byte ptr[array+di]
inc di
mov dl,dh
mov ah,02h
int 21h
loop L
mov ah,4Ch ; Service 4Ch - Terminate with Error Code
mov al,0 ; Error code
int 21h ; Interrupt 21h - DOS General Interrupts
ret
array db 256 dup (?) ; Array
x db ? ; Size of the array
ten db ?
text db "Enter number of elements in array: $"
elem db ? ; A single digit from the inputt value
sum db 0 ; Inputt value transformed into number
end start
Code written in TASM as a .com executable. It has some irrational things here and there but it's just for the clarity and due to the fact it's just a draft. Hugely appreciate your help! Thanks!
P.S. I'll be modifying the code over time in case you'll give me some advise.