decoding fat16 hex to seconds
Question
I am trying to convert fat16 hex to get time hr:min:sec,I am getting hour and minutes right but I am having trouble with seconds.
first 5 bits is hour, next six bits are minutes, and the last 5 bits are seconds(result times 2)...
so if I enter a fat16 hex 0154 it is supposed to give me 10 hours, 32 minutes and 2 seconds, but I am not sure how to get seconds ? If I shift left for seconds how I am supposed to times it by 2 ?
this is what I have
INCLUDE Irvine32.inc
.data
vFAT16 BYTE "Enter FAT16 to convert: " ,0
vTIme BYTE "--:--:--" ,0
.code
main PROC
;--------- Enter Code Below Here
call Clrscr
;-------------------------
mov dh, 11
mov dl, 0
call Gotoxy
mov edx, OFFSET vFAT16
call WriteString
;-------------------------
mov dh, 12
mov dl, 0
call Gotoxy
;-------------------------
call ReadHex
ror ax, 8
mov ecx, eax
and ax, 1111100000000000b
shr ax, 11
mov bh, 10
div bh
add ax, 3030h
mov word ptr [vTime+0], ax
mov eax, ecx
and ax, 0000011111100000b
shr ax, 5
mov bh, 10
div bh
add ax, 3030h
mov word ptr [vTime+3], ax
and ax, 0000000000011111b
shl ax, 11
mov bh, 1
div bh
add ax, 3030h
mov word ptr [vTime+6], ax
mov edx, offset vTime
call Writestring
xor ecx, ecx
call ReadString
exit
main ENDP
END main
Solution
Ok, after re-reading, edit... So you need to multiply the seconds by 2, after using and
to mask out the extra bits. You could use mul
, but multiplying by two (or any power of 2) can be done with shift left (same as division by any power of 2 can be done by shifting right).
So, simply use shl ax, 1
for seconds. This multiplies ax
by 2, which is what you want.
You are also missing the mov eax, ecx
before processing seconds.
Then convert to 2 ASCII decimal digits same way as with minutes or hours. That means, you still need to divide by 10 when you convert seconds to 2 decimal digits, not by 1 as in the code (I mean, division by 1 does nothing...).
The 10 there is for conversion to decimal, not for something else. And it works, because you get the result of division in AL, and remainder in AH. And when you add 0x3030 to AX, you actually add 0x30 to AH and 0x30 to AL, and 0x30 is ASCII code of '0', so number in range 0..9 gets converted into a character '0'...'9', both for AL and AH in one operation. And then, x86 is little endian CPU, which means, when you store AX, it first stores AL, and then AH, so you actually get the digits in right order in destination string without swapping AL and AH.
It's worth noting, that this works only as long as there is no overflow, that is initial value of AX is in range 0..99. If it is something else, you get garbage output.