Reputation: 173
I am trying to print the numbers simply in the sequence i.e
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
using Loop, First i converted each number into Hexa printed it reset it to the decimal increment by 1 and then print the next until the number is equal to 9, When the number is equal to 9 i used DAA to simply the number and after rotating and shifting the number i eventually stored the result in the string.
The output is just fine till the 16, but after 16 the sequence repeats itself,
Desired output:
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
Current Output 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,11,12,13,14,15
Why does it happens so ???
Here is my Code,
MOV CX,20 ;Number of Iterations
MOV DX,1
L1:
PUSH DX
ADD DX,30H
MOV AH,02H ;PRINT Content of DX
INT 21H
POP DX
ADD DX,1
CMP DX,09d ;If number is Greater than 9 jump to L2
JA L2
LOOP L1
L2:
PUSH DX
MOV AX,DX
DAA ;Convert to the Decimal
XOR AH,AH ;SET AH to 0000
ROR AX,1
ROR AX,1
ROR AX,1
ROR AX,1
SHR AH,1
SHR AH,1
SHR AH,1
SHR AH,1
ADC AX,3030h
MOV BX,OFFSET Result
MOV byte ptr[BX],5 ; Length of the String
MOV byte ptr[BX+4],'$' ;5th position of string , $=Terminator
MOV byte ptr[BX+3],AH ;2nd Number onto 4th position
MOV byte ptr[BX+2],AL ;3rd number onto 3rd Position
MOV DX,BX
ADD DX,02 ;1st 2 positions of String are type of string and
length respectively
MOV AH,09H ;to print the string
INT 21H
POP DX
ADD DX,1
LOOP L2
MOV AH,4CH ;Return control to the DOS
INT 21H
P.S: I took help from this chart in understanding the numbers.
http://www.cheat-sheets.org/saved-copy/ascii.png
Upvotes: 3
Views: 10129
Reputation: 1
.model small
.stack 100
.code
mov ax, 0ffffh ; hex number to find it's bcd
mov bx, 0000
mov dh, 0
l9 : cmp ax, 10000 ; if ax>10000
jb l2
sub ax, 10000 ; subtract 10000
inc dh ; add 1 to dh
jmp l9
l2 : cmp ax, 1000 ; if ax>1000
jb l4
sub ax, 1000
add bx, 1000h ; add 1000h to result
jmp l2
l4 : cmp ax, 100 ; if ax>100
jb l6
sub ax, 100
add bx, 100h ; add 100h to result
jmp l4
l6 : cmp ax, 10 ; if ax>10
jb l8
sub ax, 10
add bx, 10h ; add 10h to result
jmp l6
l8 : add bx, ax ; add remainder
; to result
mov ah, 02
mov cx, 0204h ; Count to display
; 2 digits
go: rol dh, cl
mov dl, dh
and dl, 0fh
add dl, 30h ; display 2 msb digits
int 21h
dec ch
jnz go
mov ch, 04h ; Count of digits to be
; displayed
mov cl, 04h ; Count to roll by 4 bits
l12: rol bx, cl ; roll bl so that msb
; comes to lsb
mov dl, bl ; load dl with data to be
; displayed
and dl, 0fH ; get only lsb
cmp dl, 09 ; check if digit is 0-9 or letter A-F
jbe l14
add dl, 07 ; if letter add 37H else only add 30H
l14: add dl, 30H
mov ah, 02 ; Function 2 under INT 21H (Display character)
int 21H
dec ch ; Decrement Count
jnz l12
mov ah, 4cH ; Terminate Program
int 21H
end
Upvotes: 0
Reputation: 1452
8086 code only allowed an immediate of 1 (or cl) for a count on shifts and rotates. To enable 286 code, tell Tasm ".286" at the top of your file. That's a guess.
The way I remember I used to print a two-digit number in al:
aam
add ax, 3030h
xchg al, ah
int 29h
mov al, ah
int 29h
Upvotes: 4
Reputation: 459
Just giving it a try, though I'm not sure, and I can't quickly test this.
But instead of using two loops I'd recommend using one for the whole bunch of numbers.
Furthermore I have the feeling that the problem has to do with the DAA
instruction, which I'm not used to, since it is not supported in 64 bit mode.
Anyway, here's what I'd do:
mov cx,20
mov al,1
mov bl,10 ; divisor
mov bp,offset Result ; no need to load this in the loop!!!
L1: mov dx,ax ; save to register, not to stack
cmp ax,09d
ja L2 ; number has two digits
add al,30h ; ASCII addend
; insert your output code here
jmp L3 ; jump over the two digit code
L2: xor ah,ah
div bl ; divides AX by ten (no rotate or shift needed)
; quotient in AL, remainder in AH (correct order for little endian)
add ax,3030h
; insert your output code here (note that the buffer/string address is loaded to BP)
L3: mov ax,dx
inc ax
loop L1
; done
If you wouldn't mind if one-digit numbers had a leading zero, it'd be even easier.
The div
instruction is probably more expensive than daa
plus ror
plus shr
, but your quad-rotate/shift will be even worse :-/
(As I said, I could not try it... leaving this open to you... if it doesn't work, just ask back.)
—
[update:
Another approach, especially to spare the div
in this trivial case of digit separation, would be to add 6 to numbers greater nine (i. e. 10d = 0ah --(+6)--> 16d = 10h; this is what daa
also does), then you can get along with the rotate/shift combination you used before.
Even better were to add 246, then to AX
, after which you can simply use ror ax,8
(or rol
— doesn't matter in this case), i. e. 10d = 0ah --(+246)--> 256d = 100h, as well 15d = 0fh --(+246)--> 261 = 105h. Rotate it to be 0001h or 0501h respectively, add 3030h, and you're done.
/update]
[update level="2"
What the fun... I actually intended to write it in the first level update, but forgot it somehow: instead of rol
ling by 8, or — if your TASM really doesn't support rol
ling by immediate — eight times rolling by one, you can of course also make use of the xchg
instruction, which swaps values between registers, in this case
xchg al,ah
would do the job of swapping the contents of those two registers.
There's also a bswap
instruction for reversing the byte order within a register, but it's obviously only available for registers of 32+ bits width.
/update]
Upvotes: 3