Page 2 of 2

Posted: Wed May 14, 2008 7:22 am
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.

Posted: Wed May 14, 2008 9:39 pm
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

Posted: Thu May 15, 2008 7:15 am
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.

Posted: Thu May 15, 2008 12:35 pm
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).

Posted: Thu May 15, 2008 12:38 pm
by AJ
Hi,

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

Cheers,
Adam