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 :-(
So I get
Number of heads = 0
Number of cylinders = 0
Number of sectors = 0
For completeness the code for the put_str function
and the print_num function
Charlie Benger-Stevenson
Hart Hill IT Ltd
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 :-(
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