variable byte in assembly set to 48 [duplicate] - c

I am using tasm. It is a simple program that reads the inputs from user and add the two numbers up. However, my output is displaying letters according to their letter position
For example, 3+5=h (8)
I want it to display in integer number.
.model small
.stack 100h
.data
input db 13,10,"Enter a number : ","$"
output db 13,10,"The sum is ","$"
.code
main proc
mov ax,#data
mov ds,ax
;INPUT 1
mov ah,9
mov dx, offset input
int 21h
mov ah,1
int 21h
mov bl,al
;INPUT 2
mov ah,9
mov dx, offset input
int 21h
mov ah,1
int 21h
add bl,al
;OUTPUT DISPLAY
mov ah,9
mov dx,offset output
int 21h
mov ah,2
mov dl,bl
int 21h
;END
mov ax,4c00h
int 21h
main endp
end main

Your input digits are ASCII characters, so ‘1’ is actually 31h, for example. So when you calculate 1+1 your are getting 31h+31h=62h which is the ASCII character ‘b’.
To convert your input digits to their equivalent integer values you need to subtract ‘0’ (30h).
Conversely to output integer digits as ASCII characters you will need to add ‘0’.

Related

Code stuck at an infinite loop when finding the nth fibonacci number

I was trying to find the nth Fibonacci number e.x n=3, output = 1
so my logic was this
a = 0
b = 1
input n
si 0
n>2
loop
temp = b
b = a+b
a = b
loop if si/=cx
print b
This is my pseudo code logic. When I tried to implement this I am stuck in an infinite loop
.MODEL SMALL
.STACK 100h
.DATA
STRING0 DB 'Enter INDEX $'
.CODE
MAIN PROC
MOV AX,#DATA
MOV DS,AX
LEA DX, STRING0
MOV AH,9
INT 21H
MOV AH, 2
MOV DL,0AH ;NEW LINE
INT 21H
MOV DL,0DH
INT 21H
MOV AH,1
INT 21H
SUB CX,CX
MOV CL,AL
MOV SI,0
MOV AX,0
MOV BX,1
LOOP1:
PUSH BX
ADD BX,AX
POP AX
INC SI
LOOP LOOP1
MOV DX,BX
MOV AH,9
INT 21H
MAIN ENDP
END MAIN
I use EMU 4.08. The code us stuck at an infinite loop. I have no idea why
I did SUB cx,cx to move the AL value to CL and use CL as counter otherwise it gives me error that the code failed to send 8bit data to 16bit
I was trying to find the nth Fibonacci number e.x n=3, output = 1
From your example I understand that you consider the Fibonacci sequence to begin with 0, 1, 1, 2, 3, 5, 8, 13, 21, ...
Fibonacci himself started his sequence from 1, 2, 3, 5, 8, ...
See the Wikipedia article https://en.wikipedia.org/wiki/Fibonacci_number
I didn't follow your pseudo code too much as it has flaws of its own!
Why your assembly program fails
You say your "code is stuck at an infinite loop", but that's not really the case. It is just that your loop executes an extra 50 iterations. The reason is that the DOS.GetCharacter function 01h gives you an ASCII code, that you have to convert into the digit that the pressed key represents. eg. If you press 3, DOS gives you AL=51, and you need to subtract 48 to obtain the inputted digit which is 3.
But wait, don't use this number 3 as your loop counter already! Since the 1st and 2nd Fibonacci numbers are known from the start, calculating the 3rd Fibonacci number requires just 1 iteration of the loop. Account for this and subtract 2 beforehand.
Once your program has found the answer you simply move the result from BX to DX, and expect the DOS.PrintString function 09h to output the number. It can't do that. It's a function that outputs a series of characters (so a string beginning at the address in DX), however your result is still a number in a register. You have to convert it into its textual representation. Displaying numbers with DOS has all the fine details about this conversion!
Next code allows the user to input a single-digit from 1 to 9
...
mov ah, 01h ; DOS.GetCharacter
int 21h ; -> AL = ["1","9"]
sub al, 48 ; -> AL = [1,9]
cbw ; -> AH = 0
mov cx, ax ; -> CX = [1,9]
xor ax, ax ; -> AX = 0
dec cx
jz PrintIt ; 1st Fib is 0
inc ax ; -> AX = 1
dec cx
jz PrintIt ; 2nd Fib is 1
cwd ; -> DX = 0
CalcIt: ; 3rd Fib and others
xchg ax, dx
add ax, dx
loop CalcIt
PrintIt: ; AX is at most 21 (because of the limited input)
aam
add ax, 3030h ; Conversion into text
xchg al, ah
cmp al, '0'
mov dh, 02h ; DOS.PrintCharacter
xchg ax, dx
je Ones
int 21h
Ones:
mov dl, dh
int 21h
Because in your program the output is very limited, I used a special code to display at most 2 digits. For the general case of outputting numbers see this Q/A.
I think this should be good:
.MODEL SMALL
.STACK 100h
.DATA
STRING0 DB 'Enter INDEX $'
STRING1 DB 'OUTPUT: $'
.CODE
MAIN PROC
MOV AX,#DATA
MOV DS,AX
LEA DX, STRING0
MOV AH,9
INT 21H
MOV AH, 2
MOV DL,0AH ;NEW LINE
INT 21H
MOV DL,0DH
INT 21H
MOV AH,1
INT 21H
SUB CX,CX
SUB AL,30H ;To convert char into digit value
MOV CL,AL
MOV SI,0
MOV AX,0
MOV BX,1
LOOP1:
PUSH BX
ADD BX,AX
POP AX
INC SI
LOOP LOOP1
MOV AH, 2
MOV DL,0AH ;NEW LINE
INT 21H
MOV DL,0DH
INT 21H
LEA DX, STRING1
MOV AH,9
INT 21H
;Print the result
MOV AX,BX
MOV SI,0
;Push digits from right to left into stack
LOOP2:
MOV DL,10
DIV DL
PUSH AX
MOV AH,0
INC SI
CMP AL,0
JNE LOOP2
;Pop digits from stack and print them
LOOP3:
POP DX
MOV DL,DH
MOV DH,0
ADD DL,30H ;To convert digit to char
MOV AH,2
INT 21H
DEC SI
CMP SI,0
JNE LOOP3
HLT
MAIN ENDP
END MAIN

Printing a triangle with incrementing digits instead of asterisks

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

Enter and Display a vector in x86 Assembly

I am trying to learn TASM Assembly and i need your help.
I made this code which introduces a vector from the keyboard and than it displays it on the screen with the elements sum. The problem is that when it displays it displays some weird characters but the sum works.
Hope you can help me
TITLE vectors
.model small
.stack 100H
.data
msg1 db 10,13,"Enter the lenght of the vector$"
msg2 db 10,13,"Enter the vector elements $"
msg4 db 10,13,"The sum is $"
msg3 db 10,13,"The entered vector is $"
msg5 db " $"
vector db 0
sum db 0
x db 0
.code
main PROC
MOV ax,#data
MOV ds,ax
MOV ah,9h
LEA dx, msg1
int 21h
MOV ah,1h
int 21h
LEA Si,vector
MOV cl , al
MOV x,al
SUB cl , 30h
MOV sum , 0
Introducere:
MOV ah, 9h
LEA dx, msg2
int 21h
MOV ah,1h
int 21h
SUB al,30h
MOV [Si] , al
ADD Si, 1
ADD suma,al
DEC cl
JNZ Introducere
JZ Afisare1
Afisare1:
MOV ah,9h
LEA dx, msg3
int 21h
MOV cl,x
SUB cl,30h
LEA Si,vector
JMP Afisare2
Afisare2:
MOV dx,[Si]
ADD dx,30h
MOV ah,2h
int 21h
LEA dx,msg5
int 21h
INC Si
DEC cl
JNZ Afisare2
JZ Afisare3
Afisare3:
MOV ah,9h
LEA dx,msg4
int 21h
MOV dl,sum
ADD dl,'0'
MOV ah,2h
int 21h
MOV ah,04ch
int 21h
main ENDP
END main
The problem is that when it displays it displays some weird characters but the sum works.
These weird characters come from the ommission of the required function number for displaying your msg5. Currently, instead of showing a nice separating space, you get output of the low byte from msg5's address.
MOV ah,2h
int 21h
LEA dx,msg5
<<<<< Here is missing `mov ah, 09h`
int 21h
vector db 0
sum db 0
x db 0
With this definition of vector you reserve just 1 byte to store your inputs. That's not enough! Since your entire program works with single digit numbers, the length of the vector could range from 1 to 9. Therefore you need to make this change:
vector db 9 dup (0) ;This reserves 9 bytes
sum db 0
x db 0
Since your entire program works with single digit numbers and that you output the sum as a single digit number also, you can not be too generous with the values for the inputted numbers. An example that will work follows:
Enter the lenght of the vector3 <<<<< You're missing a space character here!
Enter the vector elements 2
Enter the vector elements 5
Enter the vector elements 1
The entered vector is 2 5 1
The sum is 8

How to show a string 10 times using while loop in assembly language?

how to show string 10 times in assembly language?
Here is my code
.model small
.stack 100h
.data
msg db 'rashed $'
.code
main proc
mov ax,#data
mov ds,ax
lea dx,msg
mov ah,9 ;string output
int 21h
mov dx,0 ;dx counts characters
mov ah,9 ;prepare for read
int 21h
while_:
cmp al,0dh ;carriage return?
je end_while ;yes exit
inc dx ;not carrage return,increament count
int 21h ;read character
jmp while_ ;loop back
end_while:
exit:
mov ah,4ch
int 21h
main endp
end main
output is:
i want to show this string 10 times but the string subtracts??
how to show that 10 times??
mov dx,0 ;dx counts characters
To show the same text a number of times, choose a counter register different from the registers that are required to perform the output (In your case AX and DX). I suggest putting the counter in CX.
mov cx, 11
while_:
dec cx ;Change counter
jz end_while ;Exit after 10 iterations
mov ah, 9
int 21h ;Print string
jmp while_ ;Loop back
end_while:
Because a while-loop tests the condition first, I assigned 11
instead of 10.

Assembly programing bug

I'm new at programming assembly. Now I'm trying to write a program that converts number from decimal to binary. But I got stuck with one program while trying to input. After i output msg2 and get into loop, program doesn't turn off. I can input a lot of numbers and program doesn't turn off. I guess problem is in convertnumber: cmp si,cx (si is how many numbers I have to input, cx- how many numbers I have already written), but I am not sure about that. Where have I made a mistake and how could I correct it?
.MODEL small
.Stack 100h
.DATA
msg0 db 'how many numbers will include your input number(example. 123 is 3 numbers)? $'
msg1 db 'Now input number from 0 to 65535: $'
number db 255, ?, 256 dup ('$')
numberinAscii db 255, ?, 256 dup ('$')
enterbutton db 13,10,'$'
.CODE
start:
mov ax, #data
mov ds,ax
mov ah,09h
mov dx, offset msg0 ; first message output
int 21h
xor ah,ah ; function 00h of
int 16h ; int 16h gets a character (ASCII translation in AL)
int 3
mov bl,al
mov dl,al
mov ah,02h ; function 02h - display character
int 21h ; call DOS service
mov ah,09h
mov dx, offset enterbutton
int 21h
mov ah, 09h
mov dx, offset msg1 ; output second message
int 21h
jmp covertHowMany ; converting number that we entered
next:
xor si,si
mov si, ax ; number that we entered now is in si
xor cx,cx
mov cx,0 ;cx=0
enterfirstnumber: ;entering first number (example 123, first number is 1)
xor ah,ah
int 16h ; int 16h gets a one character
int 3
mov bl,al
mov dl,al
mov ah,02h ; function 02h - display character
int 21h ;
jmp convertnumber ; converting this number
input: ;converting number from ascii char to ascii integer
mov ax,bx
mov dx,10
mul dx ; ax:=ax*10
mov bx,ax ; number that I try to convert is in bx now
xor ah,ah
int 16h ; int 16h gets a character (ASCII translation in AL)
int 3
mov bl,al
mov dl,al
mov ah,02h ; function 02h - display character
int 21h
jmp convertnumber
convertHowMany:
sub al,30h ; convert from ascii character to ascii number
jmp next
convertnumber:
sub al,30h
add bx,ax
inc cx
cmp cx, si
jne input
jmp ending
ending:
mov ax,04C00h
int 21h
end start
I see at least two problems with your code:
The first is that when you reach convertHowMany you assume that AL still contains the character that the user typed in. That will not be the case, since both INT 21h/AH=02h and INT 21h/AH=09h modify AL. You'll have to save and restore the value of AL somehow (e.g. by pushing and popping AX).
The second problem is how you initialize SI before the loop. You're moving the value of AX into SI, which means both AL and AH. AH is not zero at that point, because you've just used INT 21h/AH=09h.
You could change the sequence xor si,si / mov si,ax into something like mov si,ax / and si,0FFh.

Resources