⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loader_hybrid_com.asm

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 ASM
字号:
; loader_hybrid_com.asm;; This is a DOS command-line loader for RTEMS executables running on; the Technologic Systems TS-1325 Embedded PC.;; It loads a DOS file given on the command line to the address `KernelBase',; and then transfers control there. It uses DOS file I/O commands to read from; the A: flash disk, and direct memory access to read from the C: ramdisk.;; Copying uses protected flat mode, so kernelbase could be above 1MB.; It does not initialize protected mode before transferring control; to the RTEMS executable image.;; Compile with: nasm -o loader.com loader_hybrid_com.asm;; Tony Ambardar (c) 1999; E.C.E. Department; University of British Columbia%include "ts1325.inc"    ; Some useful LED and button macros; IMPORTANT: [org xxx] MUST be the same as RelocAddr below.[org E000h][bits 16]; Only these three definitions may need to changeKernelBase equ  08000h   ; Where (32-bit) to locate and run RTEMS executableRelocSeg   equ  9000h    ; Segment to relocate code.RelocAddr  equ  0E000h   ; Address to relocate code, same as "org" above; Next three used in GDTRelocBase  equ  RelocSeg*16Reloc15    equ  RelocBase & 0FFFFhReloc23    equ  RelocBase / 10000hBuffer     equ  RelocAddr+400h   ; In same segment as RelocSegBuffSiz    equ  200h             ; Size of disk read + copyStackSeg   equ  RelocSegStackSiz   equ  40hStackAddr  equ  Buffer+BuffSiz+StackSiz; Used to jump to kernel in real modeKernelAddr equ  KernelBase & 0FFFFhKernelSeg  equ  (KernelBase - KernelAddr) / 16; Used to load from the ramdiskExtended   equ  100000h  ; Start of extended memory / C: ramdiskOffsetBPB  equ  0Bh      ; Start of BIOS param block in bootsector; Command-line parametersParamLen   equ  80h      ; Byte length of command line paramsParamStr   equ  82h      ; Start of param string; The ORG address above means pre-relocation addresses are wrong. The; following macro fixes these up.%define PRE_RELOC_ADDR(addr) (addr-CodeStart+100h)CodeStart:mov  dx, PRE_RELOC_ADDR(Greet)mov  ah, 9hint  21hmov  ax, 0b021h       ; Exit to DOS if push-button switch pressedint  15hand  al, 01h          ; Bit 0 == 0 if button pressedjz   ButtonExitxor cx, cxmov cl, [ParamLen]   ; See if there is a command line argjcxz NameErrordec  cx              ; Nix leading space. Is this standard?cmp  cx, 12          ; Limit to 12 chars: e.g. ABCDEFGH.IJKjg   NameError                     ; Damn. Should make sure of no ':' or '\' chars too.; Required by "relocated" [org] statement abovemov  di, PRE_RELOC_ADDR(FName)  mov  si, ParamStrrepnemovsb                ; Copy command line arg; Make sure no ':' in filename. This forces using the default dir.mov  di, PRE_RELOC_ADDR(FName)mov  al, ':'mov  cx, 12repnescasbje   NameErrorjmp  RelocateButtonExit:mov  dx, PRE_RELOC_ADDR(Button)jmp short  DosPrintNameError:mov  dx, PRE_RELOC_ADDR(FError)jmp short  DosPrintDosError:            ; Only call this AFTER relocationmov  dx, RErrorDosPrint:mov  ah, 9hint  21hDosExit:mov  ax, 04C00h      ; DOS Function: Exit programint  21h             ; Call DOS. Terminate ProgramRelocate:            ; Move this code down to RelocAddrcldmov  ax, RelocSegmov  es, ax           ; Set destination = RelocSeg:RelocAddrmov  di, RelocAddrmov  si, 100h         ; Source is ds:0100h i.e. a COM filemov  cx, CodeEnd - CodeStart ; Size of all coderepnemovsb; continue in copied codejmp  RelocSeg:RelocAddr + (RelocStart - CodeStart) RelocStart:climov  ax, StackSegmov  ss, axmov  sp, StackAddrmov  ax, csmov  ds, axmov  es, ax          ; Setup segments and stackstimov  ah, 19hint  21hmov  [DDrive], al    ; Save current default drivemov  ax, 3d00h       ; DOS Function: Open the file for readingmov  dx, FName       ; Presume DS points at filename segmentint  21hjc   DosErrorGoodOpen:mov  [FHndl], ax     ; Save file handlemov  al, [DDrive]    ; Check if loading from C: drive (ramdisk)cmp  al, 2je   LoadRamdiskLoadDosdisk:; Here we are loading from A: drive. Use DOS calls to load the file into; extended memory. Then copy from extended memory to `KernelBase'. This way; we avoid overwriting DOS file I/O structures if reading directly into; conventional (<640K) memory.mov  edi, Extended   ; Destination for code read @ 1 MegReadLoop:mov  ah,3fh          ; DOS Function: Read data from the filemov  bx, [FHndl]mov  dx, Buffer      ; Address of data buffermov  cx, BuffSiz     ; Request BuffSiz bytesint  21hjc   DosErrorGoodRead:cmp  ax, cx          ; EOF reached? AX = # bytes readpushfadd  ax, 3shr  ax, 2           ; Copy buffer by dwords, # = (ax + 3)/4movzx  ecx, axmov  esi, RelocBase + Buffer     ; Source for copy, destination is in edicall CopyData32      ; Do protected-mode copypopfje   ReadLoop        ; Still data left, so read next chunkmov  esi, Extended   ; Source for copy @ 1 Megmov  ecx, edi        ; Make count in dwordssub  ecx, esiadd  ecx, 3shr  ecx, 2mov  edi, KernelBase ; Destination copycall CopyData32      ; Move code into conventional memoryjmp  RunKernelLoadRamdisk:; Here we are loading from C: drive. Use protected mode to directly access; the virtual disk sectors in extended memory and copy to `KernelBase'. ; This way we avoid using DOS file I/O calls, except for an `open' earlier; which tells us the file exists.; Copy C: "bootsector" to buffer and save the BIOS parameter blockmov  esi, Extendedmov  edi, RelocBase + Buffer     ; Must be a 32-but address...mov  ecx, 80hcall CopyData32mov  si, Buffer + OffsetBPBmov  di, SavBPBmov  cx, EndBPB - SavBPBrepnemovsb; Calculate  FAT, root dir, and data start addresses for the ramdiskxor  eax, eaxmov  ebx, eaxmov  ecx, ebxmov  ax, [ResSec]mov  bl, [NumFAT]imul bx, [SecFAT]mov  cx, [NRoot]shr  cx, 4           ; 10h directory entries per sectoradd  bx, axadd  cx, bxmov  dx, [BpSect]imul ax, dximul bx, dximul cx, dxadd  eax, Extendedadd  ebx, Extendedadd  ecx, Extendedmov  [BegFAT], eaxmov  [BegRoot], ebxmov  [BegData], ecx; Convert the saved filename to format used in directory entry. Assume; there's a `.' in it. Hopefully this won't haunt us later...mov  di, FName       ; Find the `.'mov  al, '.'mov  cx, 12repnescasbmov  bx, di          ; di points to filename extensionmov  di, DirNamemov  si, FNamemov  cx, bx          ; Make countsub  cx, sidec cxrepne                ; Copy initial part of filenamemovsbmov  di, bx          ; Find the terminating zeroxor  al,almov  cx, 4repnescasbmov  cx, di          ; Make countsub  cx, bxdec  cxmov  si, bxmov  di, DirName + 8repne                ; Copy filename extensionmovsbmov  si, DirName     ; Convert the stupid thing to upper casemov  di, simov  cx, 11Cvt2Upper:lodsbcmp  al, 'a'jb   NotLowcmp  al, 'z'ja   NotLowxor  al, 20hNotLow:stosbloop Cvt2Upper; Now load in the root directory (temporarily) to find the first cluster; of our file. Use KernelSeg:KernelAddr as temporary storage.mov  esi, [BegRoot]mov  edi, KernelBasexor  ecx, ecxmov  cx, [NRoot]shl  cx, 3           ; Each root entry is 8 dwordscall CopyData32mov  dx, [NRoot]     ; Max # of dir entriesmov  cx, KernelSeg   ; Setup segment selector for comparisonmov  es, cxmov  di, KernelAddrFindEntry:mov  cx, 11mov  si, DirNamepush direp  cmpsbpop  dije   GotEntryadd  di, 20h         ; Point to next dir entrydec  dxjnz  FindEntryint  3h              ; Should never get here...GotEntry:mov  eax, KernelBase ; Setup initial address for copymov  [CurrDst], eaxadd  di, 32 - 6      ; Load first cluster numbermov  ax, [es:di]mov  cx, ds          ; Fix `es' selector just in casemov  es, cxLoadKernel:call LoadCluster     ; Load cluster `ax' to [CurrDst], update [CurrDst]call NextCluster     ; Get next cluster number in axcmp  ax, 0FF8h       ; Repeat until EOFjb   LoadKernelRunKernel:mov  ax, KernelSeg   ; Setup data segment and transfer controlmov  ds, axjmp  KernelSeg:KernelAddr  ; Huzzah!!; Load cluster `ax' to [CurrDst], update [CurrDst]LoadCluster:push axsub  ax, 2           ; Cluster numbers start at 2movzx eax, axxor  ecx, ecx        ; Calculate bytes in a clustermov  cl, [SpClst]imul cx, [BpSect]imul eax, ecxadd  eax, [BegData]  ; Start of clustershr  ecx, 2          ; Cluster size in dwordsmov  esi, eax        ; Copy sourcemov  edi, [CurrDst]  ; Copy destinationcall CopyData32mov  [CurrDst], edi  ; Update destpop  ax              ; Restore cluster numberret; Search FAT (FAT12 format) for next cluster in file after `ax'.NextCluster:movzx ecx, ax        ; Calculate offset into FATshr  ax, 1pushfadd  cx, axmov  esi, [BegFAT]   ; Copy word containing next cluster to bufferadd  esi, ecxmov  edi, RelocBase + Bufferxor  ecx, ecxinc  ecxcall CopyData32mov  ax, [Buffer]    ; Handle odd/even cluster numberspopfjnc  EvenClustershr  ax, 4EvenCluster:and  ax, 0FFFhret; Enable the A20 line for accesses to extended memory.EnableA20:        in al,92h        or al,2        jmp short $+2        jmp short $+2        jmp short $+2        out 92h,al        ret; The CopyData32 routine copies ecx dwords from esi to edi. Both esi; and edi hold 32-bit values. CopyData32 runs in 32-bit protected mode.CopyData32:        cli	call EnableA20   ; Put here in case file I/O screws with this	                 ; or with the GDTR	lgdt [GDTStart]  ; Initialize GDTR for 32-bit protected mode        mov eax, cr0        or al, 1        mov cr0, eax     ;go to real flat mode;	LED_GRN;	PSW_WAIT        jmp  dword 8h : RelocBase+ProtJmp[bits 32]ProtJmp:;	LED_YEL;	PSW_WAIT        mov ax, 10h        mov ds, ax        mov es, ax        mov ss, ax        rep movsd       ;copy the sector to where it should be        mov ax, 20h        mov ds, ax        mov es, ax        mov ss, ax;	LED_RED;	PSW_WAIT        jmp 18h : RealJmp1  ;use code segment with 64K limit[bits 16]RealJmp1:;	LED_OFF;	PSW_WAIT        mov eax, cr0      ;back to real segmented mode        and eax, 0fffffffeh        mov cr0, eax        jmp  RelocSeg : RealJmp2RealJmp2:;	LED_GRN;	PSW_WAIT        mov ax, cs               mov es, ax        mov ds, ax        mov ss, ax        stiret; Storage for a Dos 3+ BIOS Parameter Block (for the C: ramdisk)SavBPB:BpSect	dw  0h       ; Bytes per sector, always 512SpClst	db  0h       ; Sectors per clusterResSec	dw  0h       ; Num of reserved sectorsNumFAT	db  0h       ; Num of FATsNRoot	dw  0h       ; Num of root directory entriesTotSec	dw  0h       ; Total sectorsMedia	db  0h       ; Media descriptor byteSecFAT	dw  0h       ; Sectors per FATEndBPB:CurrDst	dd  0h       ; Current destination address for copying RTEMS exec; Important (32-bit) address for the C: ramdiskBegFAT	dd  0h       ; Start of the FATBegRoot	dd  0h       ; Start of root directoryBegData	dd  0h       ; Start of data clustersDDrive	db  0h       ; Default drive: 0h = A:, 2h = C:DirName	times 11 db 32 ; Room for 8.3 directory entry nameFName   times 13 db 0  ; Room for a 12 character null-terminated stringFHndl   dw  0000hGreet	db  "RTEMS DOS Loader (c) 1999 Tony R. Ambardar",13,10,"$"Button	db  "Button pressed -- Aborting.",13,10,"$"FError	db  "Missing or incorrect file name.",13,10,"$"RError	db  "Error opening or reading file.",13,10,"$"; Global Descriptor Table used for protectd mode.; Store the GDTR in the first null GDT entryGDTStart:dw GDTEnd - GDTStart - 1dd RelocBase + GDTStartdw 0; base=0h, limit=4Gb, present, code, exec/read, conform, 32-bit dw 0ffffh   ;seg. lim. [15:0]dw 0        ;base[15:0]db 0        ;base[23:16]db 9eh      ;p=1,dpl=0,s=1 ; code: execute/read, conformingdb 0cfh     ;c: gran=4K, D/B=1(32-bit) ; f: seg. lim. [19:16] db 0        ;base[31:24]; base=0h, limit=4Gb, present, data, read/write exp. up, 32-bit SPdw 0ffffh   ;seg. lim. [15:0]dw 0        ;base[15:0]db 0        ;base[23:16]db 92h      ;p=1,dpl=0,s=1 ; data: read/write expand-updb 0cfh     ;c: gran=4K, D/B=1(32-bit) ; f: seg. lim. [19:16]db 0        ;base[31:24]; base=0h, limit=ffffh, present, code, exec/read, conform, 16-bit ; NOTE: this descriptor is used to change back to real mode.dw 0ffffh   ;seg. lim. [15:0]dw Reloc15  ;base[15:0]db Reloc23  ;base[23:16]db 9eh      ;p=1,dpl=0,s=1 ; code: execute/read, conformingdb 000h     ;4: gran=1 byte, D/B=0(16-bit) ; 0: seg. lim. [19:16] db 0        ;base[31:24]; base=0h, limit=ffffh, present, data, read/write exp. up, 16-bit SP; NOTE: this descriptor is used to change back to real mode.dw 0ffffh   ;seg. lim. [15:0]dw Reloc15  ;base[15:0]db Reloc23  ;base[23:16]db 92h      ;p=1,dpl=0,s=1 ; data: read/write expand-updb 000h     ;0: gran=1 byte, D/B=0(16-bit) ; 0: seg. lim. [19:16]db 0        ;base[31:24]GDTEnd:CodeEnd:                    ; end-of-code marker for copy

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -