flat assembler
Message board for the users of flat assembler.
Index
> OS Construction > Building a better bootloader |
Author |
|
edfed 25 Jul 2010, 13:23
use CPUID for CPU identification.
use ID flag in EFLAG to know if CPU supports CPUID. and thats all for CPU identification for the CLI (change stack) sti. it is purelly logic, because interrupts use the stack to save context, then, if you change the stack without disabling interrupts, you will have unpredicted results. |
|||
25 Jul 2010, 13:23 |
|
revolution 25 Jul 2010, 13:31
Well lots of questions:
>Is there any sense in adding code to detect the presence of a 32-bit cpu or could I just rely on exception 6 being generated on the first occurence of say MOVZX or BSF ? Don't rely on old 16-bit CPUs to generate exceptions. Always check. It is simple to do, no sense in leaving out the check. >And would such an exception crash the system in an orderly fashion ? The is no such thing as an orderly crash! >Why should I put CLI and STI around the pair of instructions to setup the stack ? Because some very old CPUs don't inhibit interrupts after SS update. Most do though. >Intel docs are not very clear on the matter of wraparounding. So if SP=2 and I wanted to push a double word, what would happen ? This one is easy to check, set up a test and see what happens. I'm not really sure, but I expect RM will fault, and PM will depend upon your limit settings. |
|||
25 Jul 2010, 13:31 |
|
bitshifter 25 Jul 2010, 19:34
Also we can screw with the flags register to check x86-ness...
http://board.flatassembler.net/topic.php?p=115968#115968 |
|||
25 Jul 2010, 19:34 |
|
egos 26 Jul 2010, 19:57
Good questions.
SeproMan wrote: Is there any sense in adding code to detect the presence of a 32-bit cpu or could I just rely on exception 6 being generated on the first occurence of say MOVZX or BSF ? Quote: Why should I put CLI and STI around the pair of instructions to setup the stack ? |
|||
26 Jul 2010, 19:57 |
|
SeproMan 01 Aug 2010, 13:14
Please review my bootloader. I made separate versions for FAT12, FAT16 and FAT32 volumes.
Upon booting it looks for an user-named program in the root directory and then executes it .COM-style. This is not true .COM because : 1) The file extension can be anything 2) SP will not be initialized at FFFEh to allow for an executable bigger than 64KB If the user wanted to run an MS-DOS EXE, I programmed a conversion utility EXE2COM (not to be confused with EXE2BIN) that basically adds an EXE loader to the program file. Code: ; **************************************** ; * BootACom v1.00 (c) 2010 Luc FRANÇOIS * ; * Last modified : 01/08/2010 * ; * Total lines : 259 lines * ; **************************************** ; DBR=0700h ; On startup CS:IP=0090h:0100h, SS:SP=0090h:0100h, DS=0090h, ES=0090h ; ---------------------------------------------- NewDBR12: jmp near Start ; ---------------------------------------------- db 'BootACom' ; +03 * bsOEMName dw ? ; +11 bpbBytesPerSector db ? ; +13 bpbSectorsPerCluster dw ? ; +14 bpbReservedSectors db ? ; +16 bpbNumberOfFATs dw ? ; +17 bpbRootEntries dw ? ; +19 * bpbTotalSectors16 db ? ; +21 * bpbMedia dw ? ; +22 bpbFATSize16 dw ? ; +24 bpbSectorsPerTrack dw ? ; +26 bpbNumberOfHeads dd ? ; +28 bpbHiddenSectors dd ? ; +32 * bpbTotalSectors32 db ? ; +36 bsDriveNumber db ? ; +37 * bsReserved1 db ? ; +38 * bsBootSignature dd ? ; +39 * bsVolumeSerialNumber db 'NO NAME ' ; +43 * bsVolumeLabel db 'FAT12 ' ; +54 * bsFileSystem ; ---------------------------------------------- db 11 dup ' ' ;Max. 11 chars (blanks padded) ; ---------------------------------------------- ; IN (ch=0,edx,es) OUT (ebx,edx) ReadSectorEx: xor ebx,ebx ; --- --- --- --- --- --- --- --- ; IN (ch=0,edx,es:bx) OUT (bx,edx) ReadSector: push di ;(1) EDX=LBA mov di,5 ;Possible retries .Retry: pusha ;(2) jmp near .CHS ;{'jmp near .CHS','push dword push edx es bx ;(4)... 0'} push 1 ;Read 1 sector push 16 ;Length of Data Address Packet mov si,sp ;DS=SS mov ah,42h jmp short .Read .CHS: push edx ;(3) mov ax,[bp+24] ;bpbSectorsPerTrack [1,63] mul word [bp+26] ;bpbNumberOfHeads [1,256] xchg cx,ax ;'mov cx,ax' -> CX=Sectors ... pop ax dx ;(3) PerCylinder div cx ;CX=SectorsPerCylinder xchg cx,ax ;'mov cx,ax' Cylinder xchg ch,cl ; -> CH=Cylinder[0-7] shl cl,6 ; -> CL[6-7]=Cylinder[8-9] xchg ax,dx ;'mov ax,dx' div byte [bp+24] ;bpbSectorsPerTrack mov dh,al ;Head or cl,ah ; -> CL[0-5]=Sector-1 inc cx ; -> CL[0-5]=Sector pusha ;(4) 'sub sp,16' mov ax,0201h ;Read 1 sector .Read: mov dl,[bp+36] ;bsDriveNumber int 13h ;BIOS 'Extended Read' or jnc .OK ; 'Read Disk Sectors' mov ah,00h int 13h ;BIOS 'Reset Disk System' popa ;(4a) 'add sp,16' popa ;(2a) dec di jnz .Retry mov cl,2 ;CH=0 jmp short FatalError .OK: popa ;(4b) 'add sp,16' popa ;(2b) pop di ;(1) add bx,[bp+11] ;bpbBytesPerSector inc edx ret ; ---------------------------------------------- Start: mov ax,(DBR-256)/16 mov bp,256 cli mov ss,ax mov sp,bp sti mov ds,ax mov es,ax mov cx,bp mov si,7C00h-(DBR-256) mov di,bp cld rep movsw jmp far 0000h:DBR+Continue ; ---------------------------------------------- Continue: stosw ;Signature <> MS-DOS (20CDh) mov [bp+36],dl ;bsDriveNumber ; ---------------------------------------------- ; Make sure CPU is 32-bit pushf ;(1) pushf pop ax xor ax,7000h ;Try flipping 'NT' and 'IOPL' push ax popf pushf pop bx popf ;(1) cmp ax,bx je CPU_OK inc cx ; -> CX=1 ; --- --- --- --- --- --- --- --- ; IN (cx) FatalError: mov ax,0E07h ;Beep [1,3] time(s) xor bx,bx int 10h ;BIOS 'Teletype Character' loop FatalError .Crash: jmp short .Crash ; ---------------------------------------------- ; Patch code if IBM/MS INT 13 Extensions are available CPU_OK: test dl,dl jns .1 ;Only for drives 80h-FFh mov bx,55AAh mov ah,41h int 13h ;BIOS 'Installation Check' jc .1 ;Not supported cmp bx,0AA55h jne .1 ;Not installed shr cx,1 jnc .1 ;No 42h-44h,47h,48h functions mov word [bp+62+11+8],6A66h ;'jmp near .CHS' -> 'push dword ; ---------------------------------------------- 0'} ; Calculate and push some temporary variables ; --------ggffffeeddddccbbbbaaaa <- BP ; LBA of FAT1 .1: movzx edx,word [bp+14] ;bpbReservedSectors add edx,[bp+28] ;bpbHiddenSectors push edx ;(a) FAT1_LBA ; LBA of Root movzx eax,word [bp+22] ;bpbFATSize16 movzx cx,byte [bp+16] ;bpbNumberOfFATs .2: add edx,eax ;FATSize32 loop .2 push edx ;(b) Root_LBA ; LBA of Data Region mov bx,[bp+11] ;bpbBytesPerSector shr bx,5 ; -> BX=RootEntriesPerSector mov ax,[bp+17] ;bpbRootEntries, each 32 bytes push ax ;(c) RootEntries .3: inc edx sub ax,bx jnbe .3 push edx ;(d) DataRegion_LBA ; Reserve memory to cache 2 FAT sectors int 12h ;BIOS 'Get Memory Size' cwd ; -> DX=0 shl ax,6 ;Convert it from KB to õ stosw ;MS-DOS has pspNXTGRAF here shl bx,1 ; -> BX=ParagraphsPerSector sub ax,bx sub ax,bx pusha ;(e) DiskBuffer ;(f) CachedFATSectors_LBA, none ;(g) ParagraphsPerSector ; ---------------------------------------------- push (DBR+512+256)/16 pop es ; Find file 'ProgramName' in Root Directory mov edx,[bp-8] ;(b) Root_LBA NextRootSector: call ReadSectorEx ; -> EBX, EDX xor di,di ;ES:DI Current Root Sector .NextRootEntry: cmp [es:di],ch ;CH=0 je .eFile ;End of Root cmp byte [es:di],0E5h ;2 lines that could be dropped je .SkipEntry ;Skip free entry test byte [es:di+11],00011000b ;dirAttributes DIRECTORY|VOL. jnz .SkipEntry ;Is no file (Could even be LFN) pusha lea si,[bp+62] ;ProgramName mov cl,11 ;CH=0 repe cmpsb popa je NameFound .SkipEntry: add di,32 ;To next entry dec word [bp-10] ;(c) RootEntries .eFile: jz eFile ;File not found! cmp di,bx ;BX=BytesPerSector jb .NextRootEntry jmp short NextRootSector ; ---------------------------------------------- FollowChain: pop ax ; ClusterToSector in EDX .NextCluster: lea edx,[esi-2] bsf cx,[bp+13] ;bpbSectorsPerCluster {1,2,4,.. shl edx,cl ;CX=[0,7] 8,16,32,64,128} add edx,[bp-14] ;(d) DataRegion_LBA mov cl,[bp+13] ;bpbSectorsPerCluster, CH=0 .LoopInCluster:call ReadSectorEx ; -> EBX, EDX call ax ;{CallBack2} loop .LoopInCluster ; ClusterToCluster push es ;(1) mov es,[bp-16] ;(e) DiskBuffer mov edx,esi ;High words are/become zero shr si,1 pushf ;(2) add dx,si ; -> DX=RoundDown(Cluster*1.5) mov si,[bp+11] ;bpbBytesPerSector {512...4096} bsf cx,si ; -> CX=[9,12] dec si and si,dx ;Offset in a sector of 1st FAT shr dx,cl ;Relative sector in 1st FAT add edx,[bp-4] ;(a) FAT1_LBA cmp edx,[bp-20] ;(f) CachedFATSectors_LBA ? je .ReadEntry ;Yes, No need to reload mov [bp-20],edx ;(f) CachedFATSectors_LBA call ReadSectorEx ; -> EBX, EDX call ReadSector ; -> BX, EDX .ReadEntry: mov si,[es:si] ;12 useful bits popf ;(2) jnc .Even .Odd: shr si,4 .Even: and si,0FFFh pop es ;(1) jmp short .NextCluster eFile: mov cl,3 ;CH=0 jmp near FatalError ; ---------------------------------------------- NameFound: movzx esi,word [es:di+26] ;dirFirstCluster mov edi,[es:di+28] ;dirFileSize test edi,edi jz eFile ;Not much of a file! ; ---------------------------------------------- ; Load file 'ProgramName' call FollowChain ;This is a de facto jump! CallBack2: sub edi,ebx ;FileSize jbe RunImage mov bx,es add bx,[bp-22] ;(g) ParagraphsPerSector mov es,bx cmp bx,[bp-16] ;(e) DiskBuffer ja eFile ;File is too big! ret ; ---------------------------------------------- ; No need to pop last callback address. Saves us 1 byte ; Start the program .COM-style ; We won't initialize SP=FFFEh to allow for executables bigger than 64KB RunImage: mov cl,(DBR+512)/16 ;CH=0 mov ss,cx mov sp,bp mov ds,cx mov es,cx push cx bp retf ; ---------------------------------------------- db 510-($-$$) dup 0 dw 0AA55h ; ---------------------------------------------- _________________ Real Address Mode. |
|||
01 Aug 2010, 13:14 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.