Clock troubles [Fixed]

Programming, for all ages and all languages.
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

Do you have a SEGMENT X USE16 at the front of this code? If not, NASM will be generating the wrong opcodes.

Other than that, I don't see why the code would crash. Best to singlestep it in bochs, and see. The DIV looks like it should work.

Besides that, your math is wrong. You don't need the DIV in the first place. To convert BCD to decimal this way, you'd need to divide by 16, not 10. Which you can do with SHR and AND.
chezzestix
Member
Member
Posts: 118
Joined: Mon May 05, 2008 5:51 pm

Post by chezzestix »

Bochs helped, it told me the system was throwing a fit because I was trying to write to address 0x00. So I changed the base write address to 0x1337 and now it works.

BTW:
How does that math work?... Why 16 instead of 10?

Final Code:

Code: Select all

cli
xor ax,ax 
mov es,ax 
mov fs,ax 
mov gs,ax 
mov ds,ax 
mov ss,ax 
mov sp,0x7C00 
sti

mov ah,01h
mov cx,2000h
int 10h

start: 
mov dx,0 
mov si,1337
mov di,1337
call gettime 
call strtime 
mov ecx,3 
loop0: 
call bcd2ascii 
loop loop0 
mov bh,0 
call asciiout 
call colonout 
call asciiout 
call colonout 
call asciiout 
call crout 
jmp start 

gettime: 
mov ah,02h 
int 1Ah 
ret 

strtime: 
mov [si],ch 
add si,8h 
mov [si],cl 
add si,8h 
mov [si],dh 
add si,8h 
ret 

bcd2ascii: 
mov bh,10h
mov ax,[di] 
mov dx,0 
div bh 
add al,30h 
add ah,30h 
mov [si],al 
add si,8h 
mov [si],ah 
add si,8h 
add di,8h 
ret 

asciiout: 
mov al,[di] 
mov ah,0Eh 
int 10h 
add di,8h 
mov al,[di] 
mov ah,0Eh 
int 10h 
add di,8h 
ret 

colonout: 
mov al,3Ah 
mov ah,0Eh 
int 10h 
ret 

crout: 
mov al,0Dh 
mov ah,0Eh 
int 10h 
ret

TIMES 510-($-$$) DB 0x00 
SIGNATURE DW 0xAA55
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

> BTW: How does that math work?... Why 16 instead of 10?

Well, it's because BCD is all based on hex digits, and hex is base 16.
The whole point of BCD is to code 2 decimal digits into separate nibbles of a byte, right?
So, let's take a date as an example. CMOS will return the Day of Month as 0x31, if today is the 31st.

If I want to convert that back to decimal, then the bottom digit is easy, right? Just AND off the bottom 4 bits. So how do I convert that top digit to a 30 (decimal)? Or, in your case, you are converting to ascii directly, so you want to convert it to a 3, and then add '0' to it. To convert a 0x30 (= decimal 48) into a 3, you need to shift it down 4 bits -- which means dividing by 16.

So, instead of doing a DIV 16 to get your values of AL and AH, you could do:

Code: Select all

mov bl, al
and al, 0xf
shr bl, 4
mov ah, bl
-- which would accomplish basically the same thing (except that al and ah would be reversed from your calculation, I think).

If the value was coded in binary, rather than bcd, then dividing by 10 is correct.
chezzestix
Member
Member
Posts: 118
Joined: Mon May 05, 2008 5:51 pm

Post by chezzestix »

Hymmm that cuts 11 cycles off my code.

My implementation of the idea (one less register):

Code: Select all

mov ah,al
and ah,0Fh
shr al,4
Works here on the school computers grandly.

Now Im going to ask a REALLY noobish question that may be a tad off topic but might as well ask it here rather than bog up the forum elsewhere.

When it boots does it copy the whole boot sector to the 7C address? I was under the impression that it only copied a peice of it but when I remo ve the disk from the school computers it just keeps ticking. Furthermore while the disk is in it only reads for half a second and then the disk goes idle (by that time the clock has already begun ticking).
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

Hi,

Yes - the entire boot sector is copied to 0x7C00.

Cheers,
Adam
Post Reply