Reputation: 11
i have a code here:
org 100h
mov ah, 2ch
int 21h
mov ah, 2
mov dl, ch
int 21h
mov ah, 2
mov dl, cl
int 21h
ret
and what i want is to display the system time. But it displays other characters instead. How do i fix that?
EDIT: how can i add a division operation here? i guess what i want is to divide ch and cl by 10 and print it individually
thanks for answers
Upvotes: 1
Views: 13724
Reputation: 11
i got it!
org 100h
mov ah, 2ch ;get time
int 21h ;
mov hour, ch
mov mins, cl
mov ah, 0 ;
mov al, hour ;divide by 10
mov bl, 10 ;
div bl ;
mov hour1, al
mov hour2, ah
mov ah, 2 ;
mov dl, hour1 ;
add dl, 30h ;
int 21h ;
;print hour
mov ah, 2 ;
mov dl, hour2 ;
add dl, 30h ;
int 21h ;
mov ah, 2
mov dl, ':'
int 21h
mov ah, 0 ;
mov al, mins ;divide by 10
mov bl, 10 ;
div bl ;
mov min1, al
mov min2, ah
mov ah, 2 ;
mov dl, min1 ;
add dl, 30h ;
int 21h ;
;print minuntes
mov ah, 2 ;
mov dl, min2 ;
add dl, 30h ;
int 21h ;
ret
hour db ? ;
mins db ? ;
hour1 db ? ;
hour2 db ? ;initialize variables
min1 db ? ;
min2 db ? ;
Upvotes: 0
Reputation: 801
This code might be helpful for you. You can find it here and download also: Timer Tick Example of Assembly Language
[org 0x0100]
jmp start
incTime: dw 0
hrs: dw 0
min: dw 0
sec: dw 0
clearScreen:
push ax
push di
push es
mov ax , 0xB800
mov es , ax
mov di , 0
nextCls:
mov word [es:di] , 0x0720
add di , 2
cmp di , 4000
jne nextCls
pop es
pop di
pop ax
ret
printTime:
push bp
mov bp , sp
push ax
push bx
push cx
push dx
push si
push di
push es
call clearScreen
mov si , 0 ;counter to use 3 prints i.e. Hrs, Min, Sec
mov ax , 0xB800
mov es , ax
mov di , 142
nextState:
mov bx , bp
sub bx , si
add bx , 8
mov ax , [bx] ;BX=BP-SI+8
mov bx , 10
mov cx , 0
nextDigit:
mov dx , 0
div bx
add dl , 0x30
push dx
inc cx
cmp ax , 0
jnz nextDigit
nextPos:
pop dx
mov dh , 0x07
mov [es:di] , dx
add di , 2
loop nextPos
add si , 2
cmp si , 6
jz return
mov dl , ':'
mov [es:di] , dx
add di , 2
jmp nextState
return:
pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
pop bp
ret 6
Clock:
push ax
inc word [cs:incTime]
cmp word [cs:incTime] , 18
jz Reset
proceedToCall:
push word [cs:hrs]
push word [cs:min]
push word [cs:sec]
call printTime
mov al , 0x20
out 0x20 , al
pop ax
iret
Reset:
mov word [cs:incTime] , 0
inc word [cs:sec]
cmp word [cs:sec] , 60
jnz proceedToCall
mov word [cs:sec] , 0
inc word [cs:min]
cmp word [cs:min] , 60
jnz proceedToCall
mov word [cs:min] , 0
inc word [cs:hrs]
cmp word [cs:hrs] , 24
jnz proceedToCall
mov word [cs:hrs] , 0
jmp proceedToCall
start:
xor ax , ax
mov es , ax
cli
mov word [es:8*4] , Clock
mov word [es:8*4+2] , cs
sti
mov dx , start
add dx , 15
mov cl , 4
shr dx , cl
mov ax , 0x3100
int 0x21
Upvotes: 0
Reputation: 44046
Hours range from 0 to 23.
Minutes from 0 to 59.
They are two digits numbers and as such must be handled.
There is no built-in service that prints numbers, the Int 21/AH=02h
prints characters, you need to transform a two digits number (an 8 bit quantity) into a two characters (two 8 bit quantities)1.
This site has plenty of examples, here is one that use only simple instructions.
ORG 100h
mov ah, 2ch ;Get time
int 21h
mov dl, ch ;Show hours
call itoa99
mov ah, 02h ;Show separator
mov dl, ':'
int 21h
mov dl, cl ;Show minutes
call itoa99
mov ax, 4c00h ;Exit
int 21h
;dl = number to display (0..99)
itoa99:
push bx
push ax ;Save registers used
xor ax, ax ;AX = 0
mov al, dl ;AX = DL
mov bl, 10d
div bl ;AL = AX/10, AH = AX mod 10
;AX contains the digits
add ax, 3030h ;Transform digit to digitals
;ASCII digits starts at 30h, digit X is the char 30h+X
;ASCII value: 30h 31h 32h 33h ... 39h
;Character: 0 1 2 3 ... 9
mov bx, ax ;Save for later
;Show the digits
mov dl, bl
mov ah, 02h
int 21h
mov dl, bh
int 21h
pop ax
pop bx
ret
1 A two digits number has... two digits.
Base 10 is a positional system, it means that the number representation is composed of weighted quantities called digits.
Each digit is itself a number, but simple enough to have an unique symbol associated, a digital.
For example the digit 4 is represented with various symbols depending on the culture: '4', 'ד', '四', 'IV', '٤', ...
To display a number in base 10, we first need to extract the digits, then convert the digits to their digitals. The final result is a numeral.
To extract the two base 10 digits of a 0-59 range number, we simply use: d0 = n mod 10, d1 = n / 10
.
Convince your self that this indeed gives the correct result and that each di
is between 0 and 9.
Upvotes: 4