×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!
  • Students Click Here

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

HDD info

HDD info

(OP)
Hi,

I am teaching myself assembly. I have books on order by am leafing my way through code snippets and trying to piece stuff together. The first exercise I have set myself is to try and get the basic HDD info from the first (80h) HDD in the machine. I am using TASM and running in DOS (16 bit)
I can make the call to the int13/08H operation successfully, my problem comes when I try and echo the results to the screen. I am using a put_str function I found, and a put_num function. The problem is that they always return 0 sad

So I get

Number of heads = 0
Number of cylinders = 0
Number of sectors = 0

CODE

mov     ax, offset driveinfomessage
call    put_str
        
push    cs              ; setup DS so we can access
pop     ds              ; our codeseg variables without
                                        ; the CS segment override
push    cs
pop     es              ; While we're at it, fix ES too!                

mov     ah,08H          ; get drive parameters
mov     dl,80H          ; for drive 80H (harddisk1)
int     13H

mov     al,dh
xor     ah,ah
inc     ax
mov     Heads,ax        ; save head count
    
mov     al,cl           ; put sector number in AL
and     ax,3FH          ; and mask off cylinder bits
mov     Sectors,ax      ; save sector count
        
mov     al,ch           ; AL = cylinder LO
mov     ah,cl           ; AH = cylinder HI...
mov     cl,6
shr     ah,cl           ; shift the HI bits down
inc     ax
mov     Cylinders,ax    ; save cylinder count
        
mov     ax,Sectors      ; multiply "sectors"
mul     Heads           ; byte "heads"
mul     Cylinders       ; and then by "cylinders"

        ; save total capacity in sectors!
mov     WORD PTR Capacity[0],ax
mov     WORD PTR Capacity[2],dx
        
        mov ax, @data
        mov ds, ax
        
        ;print out the number of cylinders
        mov     ax, offset numcylindersmessage
        call    put_str
        mov     ax, Cylinders
        call    print_num
        mov     ax, offset newline
        call    put_str
        
        ;print out the number of heads
        mov     ax, offset numheadsmessage
        call    put_str
        mov     ax, Heads
        call    print_num
        mov     ax, offset newline
        call    put_str
        
        ;print out the number of sectors
        mov     ax, offset numsectorsmessage
        call    put_str
        mov     ax, Sectors
        call    print_num
        mov     ax, offset newline
        call    put_str

For completeness the code for the put_str function

CODE

put_str: ; display string terminated by 0
        ; whose address is in ax
push ax ; save registers
push bx
push cx
push dx
mov bx, ax ; store address in bx
mov al, byte ptr [bx] ; al = first char in string
put_loop: cmp al, 0 ; al == 0 ?
je put_fin ; while al != 0
  call putc ; display character    
  inc bx ; bx = bx + 1
  mov al, byte ptr [bx] ; al = next char in string
  jmp put_loop ; repeat loop test    
put_fin:
        
pop dx ; restore registers
pop cx
pop bx
pop ax    
ret

and the print_num function

CODE

; this procedure prints number in AX,
    ; used with PRINT_NUM_UNS to print signed numbers:
    print_num proc near
        push    dx
        push    ax

        cmp     ax, 0
        jnz     not_zero

        putchar "0"
        jmp     printed

    not_zero:
        ; the check SIGN of AX,
        ; make absolute if it's negative:
        cmp     ax, 0
        jns     positive
        neg     ax

        putchar "-"

    positive:
        call    print_num_uns
    printed:
        pop     ax
        pop     dx
        ret
    print_num endp

    ; this procedure prints out an unsigned
    ; number in AX (not just a single digit)
    ; allowed values are from 0 to 65535 (FFFF)
    print_num_uns proc near
        push    ax
        push    bx
        push    cx
        push    dx

        ; flag to prevent printing zeros before number:
        mov     cx, 1

        ; (result of "/ 10000" is always less or equal to 9).
        mov     bx, 10000       ; 2710h - divider.

        ; AX is zero?
        cmp     ax, 0
        jz      print_zero

    begin_print:

        ; check divider (if zero go to end_print):
        cmp     bx,0
        jz      end_print

        ; avoid printing zeros before number:
        cmp     cx, 0
        je      calc
        ; if AX<BX then result of DIV will be zero:
        cmp     ax,bx
        jb      skip
    calc:
        mov     cx, 0   ; set flag.

        mov     dx,0
        div     bx      ; AX = DX:AX / BX   (DX=remainder).

        ; print last digit
        ; AH is always ZERO, so it's ignored
        add     al,30h    ; convert to ASCII code.
        putchar al    

        mov     ax,dx  ; get remainder from last div.

    skip:
    
        ; calculate BX=BX/10
        push    ax
        mov     dx, 0
        mov     ax, bx
        div     cs:ten  ; AX = DX:AX / 10   (DX=remainder).
        mov     bx,ax
        pop     ax

        jmp  begin_print

    print_zero:
        putchar "0"

    end_print:

        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret
    print_num_uns endp
    
    print_al proc
        cmp al, 0
        jne print_al_r
        push ax
        mov al, '0'
        mov ah, 0eh
        int 10h
        pop ax
        ret
    print_al_r:
        push ax
        mov ah, 0
        cmp ax, 0
        je pn_done
        mov dl, 10
        div dl
        call print_al_r
        mov al, ah
        add al, 30h
        mov ah, 0eh
        int 10h
        jmp pn_done
    pn_done:
        pop ax
        ret
    endp

Charlie Benger-Stevenson
Hart Hill IT Ltd
www.harthill-it.co.uk

RE: HDD info

Part of the problem you have some data in the CodeSeg and some in the DataSeg. When you go to print out, you are accessing DataSeg:Heads when you want to access CodeSeg:Heads.  Try moving your CodeSeg variables into the DataSeg, and eliminate the DS register change to the CodeSeg at the top of the listing. Also, since there is nothing prior to that point that destroys DS, the restoring of DS is uneccessary prior to printing.

RE: HDD info

(1) Have you checked that your number-writing procedures actually work correctly with known numbers. For instance, if you do mov ax, 23 and call the number-writing procedure, what does it output?

(2) If it works OK, it'd be a good idea to get it to output the number of cylinders, sectors and heads individually to check what numbers you are getting back. If anything has become zero, then the result of all your multiplies will come back as zero.

(3) On the cs = ds issue, if you are writing a .com tiny-model program then naturally cs = ds and it really doesn't matter whether you refer to things in cs or ds, except that an explicit mention of cs adds a byte to the instruction (and so far as I know slows things down very slightly).

RE: HDD info

(OP)
Did I point out I was a noob? Not really sure what Prattaratt means. Lionelhill, the answers you require are

1) Yes it works. Although only for numbers up to 9999.
2) All report zero, before going to the multiplication step.
3) Not sure that this matters, or that I understand.

I have found the emu8086.inc file on the web, which would be better to use I think. I wonder if the asm gurus would share what they do for utility functions, is emu8086.inc the industry standard? Or is there something better? I tried to include teh emu3086.inc file using an include directive but got compile time errors using TASM.

Charlie Benger-Stevenson
Hart Hill IT Ltd
www.harthill-it.co.uk

RE: HDD info

oh, right. It's years since I've gone anywhere near the disk-drive interrupts because usually dos does enough for me. Someone else here must know more. Chances are they're not doing the job you think they're doing on your system. It could even be that they're being suppressed by windows because, were they working, they'd allow direct physical access to anywhere on your hard disk, obviously just the sort of access that pleases those of a destructive nature, and not the sort of thing a reputable operating system would care to encourage.

RE: HDD info

  What I was trying to point out in my earlier posting is that you MAY be trying to access data in the wrong area.  Although the subsequent posts lead me to believe your primary problem lies with your Hardware or OS (will explain later), I want to clarify my earlier posting.
   In your code you have the following code:

CODE

...
push    cs              ; setup DS so we can access
pop     ds              ; our codeseg variables without
                                        ; the CS segment override
...

so any data accesses without a segm overide from this point will be accessing the code segment.  In a tiny segment model, they are the same as the data segment. all other models they are not.  Before you start to call the printout routines, you have the following:

CODE

...
        
        mov ax, @data
        mov ds, ax
...
  This sets the DS register back the default Data Segment, which we have noted may or may not be the same as the Code segment, which is where you have stored the HDD characteristics.  So to access both at the same time you will need to use a CS override to get at the code seg variables, or use another system of accessing the data (Read up on using the si and di registers, Hint , Hint winky smile). So while this is not the primary cause of your problem, this may or may not (depending on the Segment Model you used to assemble in) print the correct data.

  Now as to why you are getting only zeroes for your interrupt results, if the Hard drive you have is above a certain size, you have to use an extended BIOS call. I can't remember off the top of my head what that size is or what the extended BIOS call is, but I do know if the cylinder count is excess of 16383, it's going to overflow.

  Also, if you are using DOS from Windows(I believe 98 and newer versions, but correct me if I am wrong), Windows locks you out from using the BIOS hard drive interrupts for security reasons.

RE: HDD info

(OP)
Awesome post!!!!

I will read up on si and di registers, books are on their way from US - its cheaper but a longer wait for us in the UK smile

I need to get my head around what you are saying, but certainly the put_num function does not print any number larger than 9999, obviously.

What I really need is the guidance on how to do common stuff like chucking out to screen, is emu8086.inc the way to go? Or is there a "theworldsbestulilityfunctionsfor8086processors.inc" I should be using?

Thanks

Charlie Benger-Stevenson
Hart Hill IT Ltd
www.harthill-it.co.uk

RE: HDD info

Good post, prattaratt: Oops, I didn't even spot the restoring of ds. A case of not seeing what I didn't expect to see; there shouldn't be any need to restore ds unless you're working in a memory model where different bits of your program are using different data segments.

If you're doing this for self-education, you'd probably do best to skip anything refering to low-level disk manipulation since it's very unlikely to be useful to you unless you want to get into the esoteric areas of defragmentation tools and dos-style virus-writing. There are much more fun things to do with assembly.

If you haven't come across him yet, the writings of Abrash (Zen of assembler etc.) are a good read, if a little dated. Maybe he's produced more up-to-date stuff. The last I read was about the time Pentiums were newish.

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members! Already a Member? Login

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close