: and now how can u help me?what should i do?can i use lilo bootloader
: and demidecode mudule?u know dmidecode is linux module
You probably could use lilo and this dmicode-I don't know linux well, and you're no longer really working in x86 assembly at that point, so I am unable to help you any further.
What I'd do is write some code in DOS. Start with INT 12h like you first stated, get that information printing to the screen. There are lots of other bits of information you can get from the BIOS Data Area and other interrupts.
That will get you familiar with assembly language.
Then move into converting a small DOS program into a bootloader, which is not that difficult of a step. Meanwhile, tackling DMI and other hardware detection, once you've got some of the basics down, isn't a huge task, but there are many more steps involved than just "int 12" to get the data.
assembly is slow. if your goal is to learn assembly, you need to do lots of "hello world!" programs to get the hang of it first. If you want to learn how to detect hardware and display it all to the screen, perhaps assembly is too much work to make nice displays.
I found one of my first assembly programs that detects hardware and prints it to the screen. 1993! I can't believe I'm posting this...
I used MASM to compile this to a DOS .COM file.
;info
;displays a few system stats. I want to be able to figure out processor speeds!
cseg segment
assume cs: cseg,ds:cseg,es:cseg,ss:cseg
org 100h
main: jmp go
;----------------------------------------------------------------------------
;define zee variables here
;----------------------------------------------------------------------------
open1 db 0ah,0dh,"Detected configuration: ",0ah,0dh,"-----------------------",0ah,0dh,"$"
hd db "Number of hard drives: $"
biosmade db "BIOS manufacturer: $"
award db "Award$"
phoenix db "Phoenix Technologies Ltd.$"
mylex db "Mylex$"
flop db "Floppy drives: $"
totals db "Total drive space for $"
meg db "Mb $"
dosver db "DOS Version: $"
spam db "SPAM: Yes please",0dh,0ah,"$"
numpar db "Number of parallel ports: $"
numser db "Number of serial ports: $"
mouse db "Mouse driver: $"
basemem db "Base memory: $"
extended db "Extended memory: $"
biosdate db " BIOS date: $"
cpu db "CPU type: 80$"
spa1 db " COM1 address: LPT1 address: ",0dh,0ah,"$"
spa2 db " COM2 address: LPT2 address: ",0dh,0ah,"$"
spa3 db " COM3 address: LPT3 address: ",0dh,0ah,"$"
spa4 db " COM4 address: LPT4 address: ",0dh,0ah,"$"
mathco db "Math coprocessor: $"
video db "Video type: $"
cpu8088 db "88 or 8086",0dh,0ah,"$"
cpu186 db "186",0dh,0ah,"$"
cpu286 db "286",0dh,0ah,"$"
cpu386 db "386",0dh,0ah,"$"
cpu486 db "486",0dh,0ah,"$"
none db " None $"
f360 db " 360kb 5¬",22h,"$"
f120 db " 1.2Mb 5¬",22h,"$"
f720 db " 720kb 3«",22h,"$"
f144 db " 1.44M 3«",22h,"$"
f288 db " 2.88M 3«",22h,"$"
installed db "installed",0dh,0ah,"$"
nott db "not $"
vga db "VGA",0dh,0ah,"$"
mono db "Monochrome",0dh,0ah,"$"
crlf db 0ah,0dh,"$"
;----------------------------------------------------------------------------
; These are various procedures to tell us what's up
;============================================================================
;check to see if there is a mouse installed
;----------------------------------------------------------------------------
is_mouse_installed proc
push ax
push dx
xor ax,ax ; clean out the AX register
int 33h ; call interrupt 33h function 0
cmp ax,0ffffh ; compare AX and FFFFh (installed)
jz endmouse ; it is? Jump to the end!
lea dx,nott ; Not installed? Display the word "not"
mov ah,9 ; display string function
int 21h ; interrupt 21h
endmouse:
pop dx
pop ax
ret ; end o' procedure
is_mouse_installed endp
;============================================================================
;look for a math coprocessor!
;----------------------------------------------------------------------------
is_there_a_mathco_here proc
push ax
push dx
int 11h ; call interrupt 11h (Equipment check)
and ax,2 ; single out bit 1 Coprocessor bit
cmp ax,2 ; 2=installed 0=none
jz endmathco ; if installed, jump to end
lea dx,nott ; else display a NOT!
mov ah,9 ; display string function of
int 21h ; interrupt 21h
endmathco:
pop dx
pop ax
ret ; end o' procedure!
is_there_a_mathco_here endp
;----------------------------------------------------------------------------
;find what BIOS mfgr
;============================================================================
who_made_the_bios proc
push dx
push ax
push ds ; save them registerz
mov ax,0fe00h ; looking at FE00:0030 for signatures
mov ds,ax
mov ax,ds:[0030h]
pop ds
cmp ax,7741h ; look for AW (as in AWARD)
jz awardb
cmp ax,3538h ; look for 85 (copyright notice for phoenix boys)
jz phoenixb
lea dx,mylex ; hell, it must be mylex then (bad idea to assume)
jmp display_bios
awardb:
lea dx,award ; load award
jmp display_bios
phoenixb:
lea dx,phoenix ; load phoenix
display_bios:
mov ah,9 ; function 9 of int 21
int 21h ; display string
pop ax ; restore reggies
pop dx
ret
who_made_the_bios endp
;----------------------------------------------------------------------------
;hrey, so is this a vga or monochrome system? like you can't tell
;============================================================================
find_video_card proc
push ax ; save some registerz
push dx ;
mov ah,0fh ; function F of int 10 is get video params
int 10h
cmp al,3 ; 3=vga 7=mono
jz itsvga
lea dx,mono ; load up MONO!
jmp endvideo
itsvga:
lea dx,vga ; load up VGA!
endvideo:
mov ah,9 ; print it out d00d.
int 21h
pop dx ; restore some registerz!!!!!!!!
pop ax
ret ; end o' procedure!
find_video_card endp
;============================================================================
;find the number of parallel and serial ports in this puppy
;----------------------------------------------------------------------------
get_number_of_ports proc
push cx ; save a few regsiters
push dx
int 11h ; call interrupt 11h equipment check
mov bx,ax ; copy the ax register to bx
and ax,0e00h ; single out bits 9-11
and bx,0c000h ; single out bits 14-15
mov cl,9 ; shift this thing 9 times
shr ax,cl
add al,30h ; add a 30 to it to make it a decimal
mov cl,14 ; shift this puppy 14 times
shr bx,cl
add bl,30h ; add a 30 to this to make it decimal
pop dx
pop cx ; and then restore them
ret ; end o' procedure!
get_number_of_ports endp
;----------------------------------------------------------------------------
;Hey, how many hard drives we got in this thing?
;============================================================================
number_of_hard_drives proc
push ax ; save the ole AX register
push ds ; save the DS register
mov bx,0040h ; we're gunna look at 0040:0075 for a number
mov ds,bx ;
mov dl,ds:[0075h] ; pull that number into DL register
add dl,30h ; add a 30 to it to make it decimalish
mov ah,2 ; print char function for
int 21h ; interrupt 21h (prints whats in DL get it?)
pop ds ; restore that wacky DS register
pop ax ; and the AX register too
ret ; end o' procedure
number_of_hard_drives endp
;----------------------------------------------------------------------------
;what is the date the bios was made?
;============================================================================
display_bios_date proc
push ax ; save that Ax register
push bx ; and all the rest of them too
push cx
push dx
push ds ; ditto DS
MOV BX,0F000h ; BIOS date is at F000:FFF5
MOV DS,BX ; get that data segment to F000
MOV BX,0FFF5h ; whoa! caps!
MOV AH,02 ; function #2, print char in DL
MOV CX,0008 ; Gunna print 8 characters
rollit:
MOV DL,ds:[BX] ; move char into DL to print it
INT 21h ; print char
INC BX ; increment BX by 1
loop rollit ; whip back through 7 more times
pop ds ; restore that DS
pop dx
pop cx
pop bx
pop ax ; restore that AX
ret ; end o' procedure!
display_bios_date endp
;----------------------------------------------------------------------------
;get the cpu type
;============================================================================
whatcpu proc
pushf ;ok,ok, I have NO CLUE as to how this
pop ax ;whole routine works. it does, so just
and ah,0fh ;deal with it.
push ax
popf
pushf
pop ax
and ah,0f0h
cmp ah,0f0h
jnz step1
mov ax,2
mov cl,21h
shr ax,cl
test ax,1
jz itsa8088
lea dx,cpu186
mov ah,9
int 21h
jmp endcpu
itsa8088:
lea dx,cpu8088
mov ah,9
int 21h
jmp endcpu
step1:
pushf
pop ax
or ah,0f0h
push ax
popf
pushf
pop ax
and ah,0f0h
jnz step3
lea dx,cpu286
mov ah,9
int 21h
jmp endcpu
step3:
db 90h, 66h, 8bh, 0cch, 66h, 83h ;32 bit instructions!
db 0e4h, 0fch, 66h, 9ch, 66h, 58h ;I'm sooo cool to be able
db 66h, 8bh, 0d8h, 66h, 35h, 0 ;to do this.
db 0, 4, 0, 66h, 50h, 66h
db 9dh, 66h, 9ch, 66h, 58h, 66h
db 33h, 0c3h
jnz itsa486
nop
nop
lea dx,cpu386
mov ah,9
int 21h
jmp endcpu
itsa486:
lea dx,cpu486
mov ah,9
int 21h
endcpu:
ret ; end o' procedure!
whatcpu endp
;----------------------------------------------------------------------------
;Display total space
;============================================================================
free_total proc
push ax ; save the AX register
push bx ; and the BX register
push cx ; and the CX register too damnit!
mov ah,36h ; function 36h of int21=get free space
int 21h
cmp ax,0ffffh
jz so_long
push dx ; save our DX again (total clusters on disk)
mul cx ; multiply AX*CX (Sectors/clust*bytes/clust)
mov cx,ax ; throw the result into CX for storage
pop ax ; restore the DX register from above
mov bx,3e8h ; prepare to divide that by 1000
div bx ; do that divide (could be done by 1024 )
cmp dx,500 ; is the remainder bigger than 500?
jl no_round ; no, skip it
inc AX ; why, yes it is. Increase the AX register
no_round:
xor dx,dx ; clean out the DX register
mul cx ; multiply AX*CX again
div bx ; divide by another 1000
so_long:
mov dx,ax ; drop the final result into DX
pop cx ; restore that CX
pop bx ; and that BX
pop ax ; and that AX!
ret ; end o' procedure
free_total endp
;----------------------------------------------------------------------------
;get the DOS version
;============================================================================
dos_version proc
push ax ; save the ax register
push dx
mov ah,30h ; function 30 of int 21
int 21h ; = get dos version Ah=minor al=major
mov bx,ax ; save a copy of AX to BX
add al,30h ; add 30 to al to make it decimal
mov dl,al ; drop it into DL to print it.
mov ah,2 ; function 2
int 21h ; interrupt 21
mov dl,2eh ; mov a . into DL
int 21h ; print it
add bh,30h ; add BH and 30 to make minor rev a decimal
mov dl,bh ; mov BH into DL
int 21h ; print the minor rev
pop dx
pop ax ; restore that AX register
ret ; end o' procedure!
dos_version endp
;----------------------------------------------------------------------------
;get the floppy drive numbers and type
;============================================================================
floppies proc
push ax ;save that AX register again
push si ;save the SI register (used as a flag)
xor si,si ;clean out the SI register
mov dl,0 ;DL=drive # (0=A:)
getflop:
mov ah,8 ;function 8 of int 13
int 13h ;interrupt 13h
mov ax,11 ;length of string=11 bytes
mul bx ;multiply by the drive type # (0-5)
lea dx,none ;start at "None"
add dx,ax ;add it to our drive number type counter
mov ah,9 ;function 9 of int 21h
int 21h ;is print string.
cmp si,2 ;flag set?
jz enditnow ;yes, quit the procedure
mov si,2 ;set our flag
mov dl," " ;display a space
mov ah,2
int 21h
mov dl,"+" ;display a plus sign (make it look c00ler)
int 21h
mov dl,1 ;next floppy DL=1=drive B:
jmp getflop ;and start over again
enditnow:
pop si ;restore the SI
pop ax ;restore the AX
ret
floppies endp
;----------------------------------------------------------------------------
;Hex-->dec number to convert comes in via DX
;============================================================================
hex2dec proc
push ax ; save that AX
push bx ; save that CX
push cx ; save that DX
push si ; save that SI
mov ax,dx ; copy number into AX
mov si,10 ; SI will be our divisor
xor cx,cx ; clean up the CX
non_zero:
xor dx,dx ; clean up the DX
div si ; divide by 10
push dx ; push number onto the stack
inc cx ; increment CX to do it more times
or ax,ax ; end of the number?
jne non_zero ; no? Keep chuggin' away
write_digits:
pop dx ; get the digit off DX
add dl,30h ; add 30 to it to make it decimalish
call print_char ; print that puppy out
loop write_digits ; keep going!
pop si ; restore that SI
pop cx ; restore that DX
pop bx ; restore that CX
pop ax ; restore that AX
ret ; End o' procedure!
hex2dec endp
;----------------------------------------------------------------------------
;print_char procedure fer printin' 1 digit!
;============================================================================
print_char proc
push ax ; save that AX register
mov ah,2 ; function number 2
int 21h ; of interrupt 21
pop ax ; restore that AX register
ret ; end o' procedure!
print_char endp
;find the memory size
;============================================================================
base_mem_size proc
push ax
push dx
int 12h ; call interrupt 12 to get base mem size
mov dx,ax ;
call hex2dec ; display that number in decimal
mov dl,6bh ; print out a 'k'
mov ah,2
int 21h
pop dx
pop ax
ret
base_mem_size endp
;----------------------------------------------------------------------------
ext_mem_size proc
push ax
push bx
push dx
mov ah,88h ; function number 88
int 15h ; of interrupt 15 = get extended RAM count
cmp ax,0 ; is it 0? (probably cuz himem.sys)
mov dx,ax
jnz disp_mem ; nope? ok, print that number out then!
cli ; clear all interrrupts
mov dx,0070h ; port 70h kickin' 30h out to it
mov ax,0030h ;
out dx,al ;
mov dx,0071h ; readin' back in from port 71h
in al,dx ; drop that number into AL
mov bl,al ; move that number into BL to save it
mov dx,0070h ; back to port 70h
mov ax,0031h ; sending out a 31h to get the next byte
out dx,al ;
mov dx,0071h ; reading back in from port 71h
in al,dx
sti ; restore all interrupts
mov dh,al ; mov the numbers in line into DX
mov dl,bl
disp_mem:
call hex2dec ; print out that big ole number
mov dl,6bh ; 6bh? yeah! display a k (kilobytes!!)
mov ah,2 ; print that char
int 21h
pop dx
pop bx
pop ax
ret
ext_mem_size endp
;============================================================================
;display all available drive spaces
;----------------------------------------------------------------------------
display_drive_space proc
push ax ; save some registerz
push bx
push cx
push dx
mov cl,3h ; Start with drive C
displays:
int 1
mov dl,cl ; mov drive number into DL
call free_total ; call space getter
cmp dx,0ffffh ; DX will be FFFF if invalid
jz end_it ; so end it
push dx
mov dl,cl ; mov cl register to DL
add dl,40h ; add 40 to it to make it a letter
mov ah,2 ; function 2
int 21h ; of int 21=dispaly char
mov dl,":" ; now display a colon
int 21h ;
pop dx
call hex2dec ; otherwise print it
mov ah,9
lea dx,meg
int 21h
inc cl ; and keep going
jmp displays
end_it:
pop dx ; restore som registerz
pop cx
pop bx
pop ax
ret ; end o' procedure!
display_drive_space endp
;============================================================================
;display serial/parallel port addresses
;----------------------------------------------------------------------------
display_serial proc
mov ax,0040h ; we're gunna look at 0040:0000h
push ds ; save that data segment
mov ds,ax ; look into a new location
push di ; save that DI register DI will be the count
push si ; save that SI register too
mov di,0 ; start at 0
mov si,0f0fh ; row,col of our first display section
s_loop:
push dx ; save dx
push bx ; and bx
push ax ; ax too
mov ax,0200h ; function 2
xor bx,bx ; page 0
mov dx,si ; SI is the current row/col position
int 10h ; interrupt 10h is set cursor pos
add si,0100h ; add another line (row)
pop ax ; restore all those registers
pop bx
pop dx
mov ax,ds:[di] ; move base address of port into AX
mov cx,ax ; mov into into CX for safe keeping
cmp cx,0
jz No_port
mov dl,ah ; mov that 1st digit into DL
add dl,30h ; add 30h to it to make it decimalish
mov ah,02 ; print a character
int 21h
mov ax,cx ; mov our copy back into AX
xor ah,ah ; clean up the AH register
mov bx,10h ; give BL 10h
mul bx ; multiply by 10 to move the numbers up 1
mov dl,ah ; mov the next digit into dl
cmp dl,0ah ; bigger than 10? must be a letter
jge add_37 ; if so, go add 37h to it
add dl,30h ; else just add 30h to it
jmp disp_it ; go display that puppy
add_37:
add dl,37h ; duh, yeah add 37h
disp_it:
mov ah,02 ; display that character too
int 21h
mov ax,cx ; move thast number back into ax
xor ah,ah ; clean up the AH
mul bx ; mov the digits up 1
xor ah,ah ; clean it off again
mul bx ; mov the digits up again
mov dl,ah ; move that baby over to DL
cmp dl,0ah ; add either 30 or 37
jge add_37_again
add dl,30h
jmp disp_it_again
add_37_again:
add dl,37h
disp_it_again:
mov ah,02 ; display that number
int 21h
mov dl,68h ; print an h (hexadecimal!)
mov ah,2
int 21h
next_p:
inc di ; mov the counter up by 2
inc di
cmp di,8 ; are we done with the first 4?
jnz keepit ; nope, nevermind
mov si,0f34h ; yep, start at the next column
keepit:
cmp di,10h ; are we done with that wacky loop?
jz end_this ; god I hope so.
jmp s_loop
no_port:
; save the DS seggy
push ds ; push the SS in so we can
push ss ; pop it into DS (tricky eh?)
pop ds
mov ah,9 ; function
lea dx,nott
int 21h
lea dx,installed
int 21h
pop ds
jmp next_p
end_this:
pop si
pop di ; restore that Di register
pop ds ; restore that Ds register
ret
display_serial endp
;============================================================================
;hey wow! this the beginning of this program!
;============================================================================
;============================================================================
go:
mov ax,0200h ; mov cursor to 0,0
xor dx,dx
int 10h
; display a space 4000h times
mov ah,9h ; to clear the screen you ninny
mov cx,4000
mov al," "
mov bx,7
int 10h
mov ax,0200h ; move that cursor back up to 0,0
xor dx,dx
int 10h
mov ah,9
lea dx,open1 ; display opening message lines
int 21h
lea dx,cpu ; display the cpu type line
int 21h
call whatcpu ; call routine to display it
lea dx,mathco ; print mathco message
int 21h
call is_there_a_mathco_here
lea dx,installed ; print installed
int 21h
lea dx,hd ; display number of hard drives msg
int 21h
call number_of_hard_drives ; call routine to display number
lea dx,crlf ; send a CR/LF
int 21h
; lea dx,totals ; print out some totals for drive spce
; int 21h
; call display_drive_space
; lea dx,crlf
; int 21h
lea dx,flop ; display message about floppies
int 21h
call floppies ; call routine to display number/type
lea dx,crlf ; send a CR/LF
int 21h
lea dx,biosmade
int 21h
call who_made_the_bios ; yes, call that procedure
lea dx,biosdate ; display message about BIOS date
int 21h
call display_bios_date ; call routine to display it
lea dx,crlf ; send a CR/LF
int 21h
lea dx,spam ; ha! this is a joke
int 21h ; a funny one too!
lea dx,dosver ; display message about DOS version
int 21h
call dos_version ; call routine to display it
lea dx,crlf ; send a CR/LF
int 21h
lea dx,mouse ; display a mouse message
int 21h
call is_mouse_installed ; is it there?
lea dx,installed ; display "installed"
int 21h
lea dx,video ; Display video card type
int 21h
call find_video_card
lea dx,basemem ; do the bass memory thing
int 21h
call base_mem_size
lea dx,crlf
int 21h
lea dx,extended ; display memory size
int 21h
call ext_mem_size
lea dx,crlf
int 21h
lea dx,numser ;display serial ports
int 21h
call get_number_of_ports
mov dl,al
mov ah,2
int 21h ;print out the actual number of 'em
mov ax,0200h ;locate to 0Dhx25h
mov dx,0e25h
xor bx,bx
int 10h
mov ah,9
lea dx,numpar ;print out the number of parallel
int 21h
call get_number_of_ports
mov dl,bl
mov ah,2
int 21h ;print the actual number
mov ah,9 ;send a CR/LF
lea dx,crlf
int 21h
lea dx,spa1 ; print serial/parallel port 1
int 21h ; and a CR/LF
lea dx,spa2 ; repeat this 3 more times
int 21h
lea dx,spa3
int 21h
lea dx,spa4
int 21h
call display_serial ; display the addresses for 'em
mov ax,4c00h ; end this puppy
int 21h
cseg ends
end main