Після 1.10, в березні 1983, "наступила" версія 2.00. Фактично, нова операційна система. З'явилася підтримка директорій, засоби роботи з файлами у стилі UNIX (завдяки чому зразу застаріли FCB), підтримка жорстких дисків та нових форматів дискет. З'явилася можливість завантажувати драйвери пристроїв, резидентні програми, купа нових внутрішніх і декілька --- зовнішніх, команд. Крім набору засобів роботи з файлами та резидентами, з'явилися системні виклики для керування динамічною пам'яттю.
Подивимося як це все вплинуло на нашу жертву.
Подивимося як це все вплинуло на нашу жертву.
Для кращого розуміння --- див. попередні статті серії. Код -- сумісний з Flat Assembler.
Коментарі --- англійською, щоб й іноземні колеги мали шанс зрозуміти, однак англійську я знаю відверто слабенько, тому буду вдячний за зауваження та виправлення. :-)
; This file is generated by The Interactive Disassembler (IDA) ; Copyright (c) 2010 by Hex-Rays SA, <support@hex-rays.com> ; Licensed to: Freeware version ; ; Modified to compile by fasm and commented by Indrekis, indrekis2.blogspot.com ; ; Input MD5 : ED2306A7FCCEEB053801ACD5E2F0EACE ; File Name : PC-DOS_2.00\SYS.COM ; Format : MS-DOS COM-file ; Base Address: 0h Range: 100h-680h Loaded length: 580h IBMBIO_DTA = 5666h ;.8086 use16 org 100h include "my_fcb_2b.inc" start: jmp short EntryPoint1 db 8Eh ; Ћ ; ; code for mov es, word ptr [bp+di] ? db 3 ; =========================================================================== ; COM-format executables begin running with the following register values: ; AL = 00h if first FCB has valid drive letter, FFh if not ; AH = 00h if second FCB has valid drive letter, FFh if not ; CS,DS,ES,SS = PSP segment SP = offset of last word available in first 64K segment ; ( http://www.ctyme.com/intr/rb-2939.htm ) EntryPoint1: push ax ; Save AX ; Then check for DOS version. Exit if older than 1.54 ; or newer than 2.00 mov ah, 30h int 21h ; DOS - GET DOS VERSION ; Return: AL = major version number (00h for DOS 1.x) xchg ah, al ; Now AX=High:Low version cmp ax, 136h ; Why this number, instead of obvious 200h? ; May be some development version of DOS 2.0 had ; internal versions starting from 1.54? jb short WrongDOSVersion cmp ax, 200h jbe short DosVersionOK ; If version is newer, than 2.00, exit too. WrongDOSVersion: push cs ; Restore DS, but why? pop ds mov dx, aIncorrectDosVe ; "Incorrect DOS version\r\n$" mov ah, 9 int 21h ; DOS - PRINT STRING ; DS:DX -> string terminated by "$" int 20h ; DOS - PROGRAM TERMINATION ; returns to DOS--identical to INT 21/AH=00h ; =========================================================================== DosVersionOK: pop ax ; Restore initial AX, with default FCBs disk states. jmp short EntryPoint2CorrectVer ; =========================================================================== AnyArgIsInvalid: mov dx, aInvalidParamet ; "Invalid parameter$" jmp PrintMsgNExit ; =========================================================================== BadDriveLetter: mov dx, aInvalidDriveSp ; "Invalid drive specification$" jmp PrintMsgNExit ; =========================================================================== AskToInsertSysDisk: mov al, [currentDrive] add al, 40h ; Disk number (1 - A, 2 - B, ...) to disk letter. loc_134: mov [drive_letter], al mov dx, aInsertSystemDi ; "Insert system disk in drive " mov ah, 9 int 21h ; DOS - PRINT STRING ; DS:DX -> string terminated by "$" mov ax, 0C08h int 21h ; DOS - CLEAR KEYBOARD BUFFER ; AL must be 01h, 06h, 07h, 08h, or 0Ah. xor al, al ; Restore AL -- 00 means correct first FCB (we have ; already checked). EntryPoint2CorrectVer: cmp byte ptr ds:5Dh, 20h ; PSP: 5Ch-6Bh (16 bytes) -- Unopened Standard FCB 1 ; So here will be any symbol, entered after [a-z][:][\] jnz short AnyArgIsInvalid cmp al, 0FFh ; AL = 00h if first FCB has valid drive letter, FFh if not ; ( http://www.ctyme.com/intr/rb-2939.htm ) jz short BadDriveLetter ; ; Check for attempt to write system files into ; disk, we are running (and reading them) from cmp byte ptr ds:5Ch, 0 ; Check for current drive, ; disabling "sys" to self jz short BadDriveLetter mov ah, 19h int 21h ; DOS - GET DEFAULT DISK NUMBER inc al mov [currentDrive], al cmp [ds:5Ch], al jz short BadDriveLetter ; Put current driver letter in the strings, where ; it will be used in messages. mov dl, al add al, 40h ; 41h -- code for 'A', we have disk numbers, starting from, ; so to convert number to letter, should add 40h. mov byte [currentDriveChar1], al mov byte [currentDriveChar2], al ; ":/" ; DOS have directories, so determine where we are now mov si, CurDirPath ; "" mov ah, 47h int 21h ; DOS - 2+ - GET CURRENT DIRECTORY ; DL = drive (0=default, 1=A, etc.) ; DS:SI points to 64-byte buffer area ; ; currentDriveChar2 after previous code containt driver letter + "\:", ; ended with 0 (C-string), for example, "a:\", so we change directory to ; source disk root, (where sys files exists). mov dx, currentDriveChar2 ; ":/" mov ah, 3Bh int 21h ; DOS - 2+ - CHANGE THE CURRENT DIRECTORY (CHDIR) ; DS:DX -> ASCIZ directory name (may include drive) ; ; Open system files. mov ah, 0Fh mov dx, FCBext_1 int 21h ; DOS - OPEN DISK FILE ; DS:DX -> FCB ; Return: AL = 00h file found, FFh file not found or al, al jnz short AskToInsertSysDisk mov dx, FCBext_2 mov ah, 0Fh int 21h ; DOS - OPEN DISK FILE ; DS:DX -> FCB ; Return: AL = 00h file found, FFh file not found or al, al jnz short AskToInsertSysDisk ; We have found IBMBIO.COM and IBMDOS.COM files. (No check for COMMAND.COM) mov ah, 1Ah mov dx, IBMBIO_DTA int 21h ; DOS - SET DISK TRANSFER AREA ADDRESS ; DS:DX -> disk transfer buffer ; ; Both FCBs are opened, so we can set record size mov ax, 1 mov word [FCBext_1.RecordSize], ax mov word [FCBext_2.RecordSize], ax ; Read IBMBIO mov bx, FCBext_1 mov cx, 4000h ; Actual IBMBIO.COM size -- 4608d=9*512, less than 4000h. call ReadFile ; On entry BX -- FCB, DTA is set ; Saves after the FCB file date, file time and number ; of readed bytes (recors, but recors size=1) ; IBMBIO readed, proceeding to IBMDOS mov dx, IBMDOS_DTA mov ah, 1Ah int 21h ; DOS - SET DISK TRANSFER AREA ADDRESS ; DS:DX -> disk transfer buffer mov bx, FCBext_2 mov cx, 5000h call ReadFile ; On entry BX -- FCB, DTA is set ; Saves after the FCB file date, file time and number ; of readed bytes (recors, but recors size=1) ; IBMDOS readed. ; ; Both files readed, their date, time and size saved. ; mov al, [ds:5Ch] ; Target disk from PSP FCB1 mov [FCBext_2.Driver], al ; Set for FCB2 mov [FCBext_1.Driver], al ; Set for FCB1 mov [FCBext_forFind.Driver], al ; Set letter for taget disk add al, 40h ; currentDriveChar2 after previous code containt driver letter + "\:", ; ended with 0 (C-string), for example, "a:\", so we change directory to ; target disk root. mov byte [currentDriveChar2], al ; ":/" mov dx, currentDriveChar2 ; ":/" mov ah, 3Bh int 21h ; DOS - 2+ - CHANGE THE CURRENT DIRECTORY (CHDIR) ; DS:DX -> ASCIZ directory name (may include drive) ; Return DTA to default address mov ah, 1Ah mov dx, 80h ; Default DTA in PSP. int 21h ; DOS - SET DISK TRANSFER AREA ADDRESS ; DS:DX -> disk transfer buffer ; Search files by mask *.* (== ????????.???) mov ah, 11h mov dx, FCBext_forFind int 21h ; DOS - SEARCH FIRST USING FCB ; DS:DX -> FCB or al, al jnz short noFilesAtTarget ; Jump, if no files found at disk root. ; Search for IBMBIO.COM on target disk mov dx, FCBext_1 mov ah, 0Fh int 21h ; DOS - OPEN DISK FILE ; DS:DX -> FCB ; Return: AL = 00h file found, FFh file not found ; If there are files at target disk root, and ; none of them has name "IBMBIO.COM" -- tell that ; there is no room for system or al, al jnz short noRoomForSys ; If IBMDOS.COM exists, open it mov dx, FCBext_2 mov ah, 0Fh int 21h ; DOS - OPEN DISK FILE ; DS:DX -> FCB ; Return: AL = 00h file found, FFh file not found ; If there are files at target disk root, and ; no of them has name "IBMDOS.COM" -- tell that ; there is no room for system or al, al jnz short noRoomForSys mov bx, dx ; ; What is the purpose of this move? ; If IBMDOS exists on target -- delete it. mov ah, 13h int 21h ; DOS - DELETE FILE via FCB ; DS:DX -> FCB with filename field filled with ; template for deletion ('?' wildcard allowed, but not '*') ; Return: AL = 00h file found, FFh file not found ; Write system files to target noFilesAtTarget: mov dx, IBMBIO_DTA mov bx, FCBext_1 call WriteSysFile ; At call BX -- unopened tagret extended FCB, size, ; date and time is saved after the FCB, ; DX -- DTA adress mov dx, IBMDOS_DTA mov bx, FCBext_2 call WriteSysFile ; At call BX -- unopened tagret extended FCB, size, ; date and time is saved after the FCB, ; DX -- DTA adress mov dx, aSystemTransfer ; "System transferred$" WriteMsgWriteBootNExit: mov ah, 9 int 21h ; DOS - PRINT STRING ; DS:DX -> string terminated by "$" ; Restore old path for source disk. mov dx, currentDriveChar1 mov ah, 3Bh int 21h ; DOS - 2+ - CHANGE THE CURRENT DIRECTORY (CHDIR) ; DS:DX -> ASCIZ directory name (may include drive) call WriteBoot ; ; Writes boot with correct BPB for 8-track FDD's ; ; Possibly attempt to automatically fix boot for old, (1.XX), ; ; incompatible floppies. int 20h ; DOS - PROGRAM TERMINATION ; returns to DOS--identical to INT 21/AH=00h ; =========================================================================== ; Here we fall in case of errors, which occured before ; we have changed current directory. PrintMsgNExit: mov ah, 9 int 21h ; DOS - PRINT STRING ; DS:DX -> string terminated by "$" int 20h ; DOS - PROGRAM TERMINATION ; returns to DOS--identical to INT 21/AH=00h ; =========================================================================== ; At time of this error, default path has been changed -- need to restore. ; So jumpint to WrtieMsgWriteBootNExit noRoomForSys: mov dx, aNoRoomForSyste ; "No room for system on destination disk$" jmp short WriteMsgWriteBootNExit ; =========================================================================== ; This code is unused! mov dx, aIncompatibleSy ; "Incompatible system size$" jmp short WriteMsgWriteBootNExit virtual at bx bxExtFCB_t ExtFCB_t 0," "," ",0,0,0 ; To cheat fasm, needs exactly 8/3 spaces ; In fact, values are ignored. end virtual ; ============== subroutine ================================================= ; On entry BX -- FCB, DTA is set ; Saves after the FCB file date, file time and number ; of readed bytes (recors, but recors size=1) ; Procedure is exactly the same, as in PC-DOS 1.10 ReadFile: mov ah, 27h mov dx, bx int 21h ; DOS - RANDOM BLOCK READ ; DS:DX -> FCB ; CX = number of records to be read ; After the FCB we have variables IBM???_date, IBM???_time, IBM???_readed_size mov [bx+30h], cx mov ax, word [bxExtFCB_t.FileDate] ;word prt [bx+ExtFCB_t.FileDate] mov [bx+2Ch], ax mov ax, word [bxExtFCB_t.FileTime] ;word ptr [bx+ExtFCB_t.FileTime] mov [bx+2Eh], ax retn ;ReadFile endp ; ============== subroutine ================================================= ; ; Writes boot with correct BPB for 8-track FDD's ; ; Possibly attempt to automatically fix boot for old, (1.XX), ; ; incompatible floppies. WriteBoot: mov ah, 32h mov dl, [FCBext_1.Driver] int 21h ; DOS - 2+ internal - GET DRIVE PARAMETER BLOCK ; DL = drive number, 0 = default, 1 = A, etc. ; DS:BX -> Drive Parameter Block (DPB) ; ; http://www.ctyme.com/intr/rb-2724.htm ; Format of DOS Drive Parameter Block: ; Offset Size Description (Table 01395) ; 00h BYTE drive number (00h = A:, 01h = B:, etc) ; 01h BYTE unit number within device driver ; 02h WORD bytes per sector ; 04h BYTE highest sector number within a cluster ; 05h BYTE shift count to convert clusters into sectors ; 06h WORD number of reserved sectors at beginning of drive ; 08h BYTE number of FATs ; 09h WORD number of root directory entries ; 0Bh WORD number of first sector containing user data ; 0Dh WORD highest cluster number (number of data clusters + 1) ; 16-bit FAT if greater than 0FF6h, else 12-bit FAT ; 0Fh BYTE number of sectors per FAT ; 10h WORD sector number of first directory sector ; 12h DWORD address of device driver header (see #01646) ; 16h BYTE media ID byte (see #01356) ; 17h BYTE 00h if disk accessed, FFh if not ; 18h DWORD pointer to next DPB ; ---DOS 2.x--- ; 1Ch WORD cluster containing start of current directory, 0000h=root, ; FFFFh = unknown ; 1Eh 64 BYTEs ASCIZ pathname of current directory for drive mov al, [bx+16h] ; media ID byte ; ; http://www.ctyme.com/intr/rb-2590.htm#Table1356 ; FFh floppy, double-sided, 8 sectors per track (320K) ; FEh floppy, single-sided, 8 sectors per track (160K) ; FDh floppy, double-sided, 9 sectors per track (360K) ; FCh floppy, single-sided, 9 sectors per track (180K) ; See also: http://en.wikipedia.org/wiki/File_Allocation_Table#FATID push cs ; Restore spoiled DS pop ds cmp al, 0FEh ; If less -- exit from proc. ; Known ID's, less than FEh are that for 9-track FDD's jb short WriteBootExit ; If disk is single-sided --- write boot for it test al, 1 ; For known codes, last bit=1 for double-sided jz short DoWriteBoot ; Update boot image for double-sided disk mov bx, FCBext_forFind.DirectRecord ; Also points to beginning of new boot. mov word [bx+11h], 70h ; BPB -- root entries mov word [bx+13h], 280h ; BPB -- NumSectors inc byte [bx+15h] ; BPB -- MediaType inc word [bx+1Ah] ; NumberOfHeads DoWriteBoot: mov al, [FCBext_1.Driver] dec al ; FCB disk number to DOS disk number mov bx, FCBext_forFind.DirectRecord ; Also points to beginning of new boot. xor dx, dx ; Write new boot loc_280: mov cx, dx inc cx int 26h ; DOS - ABSOLUTE DISK WRITE (except DOS 4.0/COMPAQ DOS 3.31 >32M partn) ; AL = drive number (0=A, 1=B, etc), DS:BX = Disk Transfer Address (buffer) ; CX = number of sectors to write, DX = first relative sector to write ; Return: CF set on error pop ax ; Original flags are left on stack by int 26h, ; must be popped by caller. WriteBootExit: retn ;WriteBoot endp ; sp = 2 ; ============== subroutine ================================================= ; Unlike SYS 1.XX, now we have some error checking during writes. ; At call BX -- unopened tagret extended FCB, size, ; date and time is saved after the FCB, ; DX -- DTA adress WriteSysFile: mov ah, 1Ah int 21h ; DOS - SET DISK TRANSFER AREA ADDRESS ; DS:DX -> disk transfer buffer mov dx, bx mov ah, 16h int 21h ; DOS - CREATE A DISK FILE ; DS:DX -> FCB xor ax, ax mov word [bxExtFCB_t.DirectRecord], ax mov word [bxExtFCB_t.DirectRecord+2], ax inc ax mov word [bxExtFCB_t.RecordSize], ax mov ah, 28h mov cx, [bx+30h] ; Readed file size int 21h ; DOS - RANDOM BLOCK WRITE ; DS:DX -> FCB ; CX = number of records to be written ; if zero, truncate file to current random file position cmp al, 1 ; AL=01h: disk full or file read-only jz short noRoomForSys mov ax, [bx+2Ch] ; Set target file date and time, saved from source file mov word [bxExtFCB_t.FileDate], ax mov ax, [bx+2Eh] mov word [bxExtFCB_t.FileTime], ax mov ah, 10h int 21h ; DOS - CLOSE DISK FILE ; DS:DX -> FCB ; Return: AL = 00h directory update successful ; FFh file not found in directory retn ; WriteSysFile endp ; =========================================================================== db 0 currentDriveChar2 db 0,':/',0 currentDriveChar1 db 0 db 3Ah ; : db 2Fh ; / CurDirPath db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 currentDrive db 0 FCBext_1 ExtFCB_t 0,"IBMBIO ", "COM", 0,7,0 ;FCBext_1 db 0FFh ; ExtMarker ; db 5 dup(0) ; Reserved1 ; db 7 ; Attribute ; db 0 ; Driver ; db 'I', 'B', 'M', 'B', 'I', 'O', 2 dup(' '); FileName ; db 'C', 'O', 'M' ; FileExt ; db 2 dup(0) ; CurBlock ; db 2 dup(0) ; RecordSize ; db 4 dup(0) ; FileSize ; db 2 dup(0) ; FileDate ; db 2 dup(0) ; FileTime ; db 8 dup(0) ; Reserved2 ; db 0 ; CurRecord ; db 4 dup(0) ; DirectRecord IBMBIO_date dw 0 IBMBIO_time dw 0 IBMBIO_readed_size dw 0 FCBext_2 ExtFCB_t 0,"IBMDOS ", "COM", 0,7,0 ;FCBext_2 db 0FFh ; ExtMarker ; db 5 dup(0) ; Reserved1 ; db 7 ; Attribute ; db 0 ; Driver ; db 'I', 'B', 'M', 'D', 'O', 'S', 2 dup(' '); FileName ; db 'C', 'O', 'M' ; FileExt ; db 2 dup(0) ; CurBlock ; db 2 dup(0) ; RecordSize ; db 4 dup(0) ; FileSize ; db 2 dup(0) ; FileDate ; db 2 dup(0) ; FileTime ; db 8 dup(0) ; Reserved2 ; db 0 ; CurRecord ; db 4 dup(0) ; DirectRecord IBMDOS_date dw 0 IBMDOS_time dw 0 IBMDOS_readed_size dw 0 ; 0x01 file is read only ; 0x02 hidden file ; 0x04 system file ; 0x08 a special entry containing the disk's volume label ; 0x10 The entry describes a subdirectory. ; 0x20 This is the archive flag. ; 0x40 Not used; must be set to 0. ; 0x80 Not used; must be set to 0. ; ; 1Eh=11110b -- hidden, system, volume lable, directory FCBext_forFind ExtFCB_t_DR 0,"????????", "???", 0,1Eh,0, 0EBh, 2Ch, 90h, 49h ; <= 4 last - bytes of boot ;FCBext_forFind db 0FFh ; ExtMarker ; db 5 dup(0) ; Reserved1 ; db 1Eh ; Attribute ; db 0 ; Driver ; db 8 dup('?') ; FileName ; db 3 dup('?') ; FileExt ; db 2 dup(0) ; CurBlock ; db 2 dup(0) ; RecordSize ; db 4 dup(0) ; FileSize ; db 2 dup(0) ; FileDate ; db 2 dup(0) ; FileTime ; db 8 dup(0) ; Reserved2 ; db 0 ; CurRecord ; db 0EBh, 2Ch, 90h, 49h ; DirectRecord ; First 4 bytes of boot are intersected with FCB for find! NewBoot_minus_first_4_bytes db 42h, 4Dh, 20h, 20h, 32h, 2Eh, 30h, 0, 2, 2, 1, 0, 2; 0 db 40h, 0, 40h, 1, 0FEh, 1, 0, 8, 0, 1, 0, 0, 0, 0, 0; 13 db 0Ah, 0DFh, 2, 25h, 2, 9, 2Ah, 0FFh, 50h, 0F6h, 0, 2; 28 db 0CDh, 19h, 0FAh, 33h, 0C0h, 8Eh, 0D0h, 0BCh, 0, 7Ch; 40 db 8Eh, 0D8h, 0A3h, 7Ah, 0, 0C7h, 6, 78h, 0, 21h, 7Ch; 50 db 0FBh, 0CDh, 13h, 73h, 3, 0E9h, 95h, 0, 0Eh, 1Fh, 0A0h; 61 db 10h, 7Ch, 98h, 0F7h, 26h, 16h, 7Ch, 3, 6, 1Ch, 7Ch; 72 db 3, 6, 0Eh, 7Ch, 0A3h, 3, 7Ch, 0A3h, 13h, 7Ch, 0B8h; 83 db 20h, 0, 0F7h, 26h, 11h, 7Ch, 5, 0FFh, 1, 0BBh, 0, 2; 94 db 0F7h, 0F3h, 1, 6, 13h, 7Ch, 0E8h, 7Eh, 0, 72h, 0B3h; 106 db 0A1h, 13h, 7Ch, 0A3h, 7Eh, 7Dh, 0B8h, 70h, 0, 8Eh, 0C0h; 117 db 8Eh, 0D8h, 0BBh, 0, 0, 2Eh, 0A1h, 13h, 7Ch, 0E8h, 0B6h; 128 db 0, 2Eh, 0A0h, 18h, 7Ch, 2Eh, 2Ah, 6, 15h, 7Ch, 0FEh; 139 db 0C0h, 32h, 0E4h, 50h, 0B4h, 2, 0E8h, 0C1h, 0, 58h, 72h; 150 db 38h, 2Eh, 28h, 6, 20h, 7Ch, 76h, 0Eh, 2Eh, 1, 6, 13h; 161 db 7Ch, 2Eh, 0F7h, 26h, 0Bh, 7Ch, 3, 0D8h, 0EBh, 0CEh; 173 db 0Eh, 1Fh, 0CDh, 11h, 0D0h, 0C0h, 0D0h, 0C0h, 25h, 3; 183 db 0, 75h, 1, 40h, 40h, 8Bh, 0C8h, 0F6h, 6, 1Eh, 7Ch, 80h; 193 db 75h, 2, 33h, 0C0h, 8Bh, 1Eh, 7Eh, 7Dh, 0EAh, 0, 0, 70h; 205 db 0, 0BEh, 0C9h, 7Dh, 0E8h, 2, 0, 0EBh, 0FEh, 2Eh, 0ACh; 217 db 24h, 7Fh, 74h, 4Dh, 0B4h, 0Eh, 0BBh, 7, 0, 0CDh, 10h; 228 db 0EBh, 0F1h, 0B8h, 50h, 0, 8Eh, 0C0h, 0Eh, 1Fh, 2Eh; 239 db 0A1h, 3, 7Ch, 0E8h, 43h, 0, 0BBh, 0, 0, 0B8h, 1, 2; 249 db 0E8h, 58h, 0, 72h, 2Ch, 33h, 0FFh, 0B9h, 0Bh, 0, 26h; 261 db 80h, 0Dh, 20h, 26h, 80h, 4Dh, 20h, 20h, 47h, 0E2h, 0F4h; 272 db 33h, 0FFh, 0BEh, 0DFh, 7Dh, 0B9h, 0Bh, 0, 0FCh, 0F3h; 283 db 0A6h, 75h, 0Eh, 0BFh, 20h, 0, 0BEh, 0EBh, 7Dh, 0B9h; 293 db 0Bh, 0, 0F3h, 0A6h, 75h, 1, 0C3h, 0BEh, 80h, 7Dh, 0E8h; 303 db 0A6h, 0FFh, 0B4h, 0, 0CDh, 16h, 0F9h, 0C3h, 1Eh, 0Eh; 314 db 1Fh, 33h, 0D2h, 0F7h, 36h, 18h, 7Ch, 0FEh, 0C2h, 88h; 324 db 16h, 15h, 7Ch, 33h, 0D2h, 0F7h, 36h, 1Ah, 7Ch, 88h; 334 db 16h, 1Fh, 7Ch, 0A3h, 8, 7Ch, 1Fh, 0C3h, 2Eh, 8Bh, 16h; 344 db 8, 7Ch, 0B1h, 6, 0D2h, 0E6h, 2Eh, 0Ah, 36h, 15h, 7Ch; 355 db 8Bh, 0CAh, 86h, 0E9h, 2Eh, 8Bh, 16h, 1Eh, 7Ch, 0CDh; 366 db 13h, 0C3h, 0, 0, 0Dh, 0Ah, 4Eh, 6Fh, 6Eh, 2Dh, 53h; 376 db 79h, 73h, 74h, 65h, 6Dh, 20h, 64h, 69h, 73h, 6Bh, 20h; 387 db 6Fh, 72h, 20h, 64h, 69h, 73h, 6Bh, 20h, 65h, 72h, 72h; 398 db 6Fh, 72h, 0Dh, 0Ah, 52h, 65h, 70h, 6Ch, 61h, 63h, 65h; 409 db 20h, 61h, 6Eh, 64h, 20h, 73h, 74h, 72h, 69h, 6Bh, 65h; 420 db 20h, 61h, 6Eh, 79h, 20h, 6Bh, 65h, 79h, 20h, 77h, 68h; 431 db 65h, 6Eh, 20h, 72h, 65h, 61h, 64h, 79h, 0Dh, 0Ah, 0; 442 db 0Dh, 0Ah, 44h, 69h, 73h, 6Bh, 20h, 42h, 6Fh, 6Fh, 74h; 453 db 20h, 66h, 61h, 69h, 6Ch, 75h, 72h, 65h, 0Dh, 0Ah, 0; 464 db 69h, 62h, 6Dh, 62h, 69h, 6Fh, 20h, 20h, 63h, 6Fh, 6Dh; 475 db 30h, 69h, 62h, 6Dh, 64h, 6Fh, 73h, 20h, 20h, 63h, 6Fh; 486 db 6Dh, 30h, 0, 0, 0, 0, 0, 0, 0, 55h, 0AAh; 497 aIncorrectDosVe db 'Incorrect DOS version',0Dh,0Ah,'$' aInvalidDriveSp db 'Invalid drive specification$' aInvalidParamet db 'Invalid parameter$' ; ; String contains disk letter, adjusted in code, ; so consists of 3 variables. aInsertSystemDi db 'Insert system disk in drive ' drive_letter db 41h aAndStrikeAnyKe db 0Dh,0Ah db 'and strike any key when ready',0Dh,0Ah,'$' ; aNoRoomForSyste db 'No room for system on destination disk$' ; Unused string aIncompatibleSy db 'Incompatible system size$' aSystemTransfer db 'System transferred$' IBMDOS_DTA db 6 ; Trash ? db 0C4h ; Д db 2Dh ; - db 0EBh ; л db 0D5h ; Х db 3Ch ; < db 0Eh db 75h ; u db 0Dh db 83h ; ѓ db 3Eh ; > db 0C1h ; Б db 2Dh ; - db 0 db 75h ; u db 0DBh ; Ы db 0FEh ; ю db 6 db 0C2h ; В db 2Dh ; - db 0EBh ; л db 0C4h ; Д db 3Ch ; < db 0Fh db 75h ; u db 0D1h ; С
Розмір --- 1 408 байт, сильно розрослася. Хоча, 512 з них --- новий бут-сектор, і в коді трохи сміття, тому реальне зростання не таке велике. Але є.
Скачати код, разом із лістингом, згенерованим IDA, скомпільованим файлом та, для порівняння, оригінальним SYS.COM, можна тут. Скомпільований код, з точністю до опкодів-синонімів, тотожній оригінальному.
До речі, придумав швидкий спосіб перевіряти відмінні опкоди на "синонімічність". Шукати по таблицях довго, незручно, вразливо до помилок. Однак, якщо дизасемблювати новий файл, (за допомогою IDA), можна звіряти команди за адресами, де байти оригінального та скомпільованого файлів відмінні. Сильно допомагає в цьому вкладка HexView-A.
Алгоритм роботи
Нова версія, перш за все, зберігає AX (нагадуємо, AL містить 00, якщо в першому FCB з PSP коректний диск), перевіряє версію DOS. Якщо версія менша за 1.54 (1.36h) або більша за 2.00, вийти, повідомивши "Incorrect DOS version". Інакше продовжити. DOS 1.XX охоплюється цією перевіркою, так як виклик "AH=31h/INT 21h", "GET DOS VERSION" в ньому не існує, а для таких викликів DOS поверне 0. Між початком програми та перевіркою версії DOS є два загадкових байти, які ніби ніде не використовуються...
UPDATE 06-2013: Подібні байти є і в пізніших версіях SYS.COM, але лише аналізуючи FORMAT.COM (PC-DOS 1.00), яка теж містить ці загадкові байти, виявив що це -- адреса копії бут-сектора в пам'яті (не в файлі -- там вона менша на 100h). Принаймні, для всіх перевірених SYS.COM, дане правило виконується, після стрибка до точки входу вони містять адресу boot-сектора, яка в коді ніде не використовується.
Версія 1.54 в перевірці показує, що існували внутрішні версії, які були ще 1.XX, але вже підтримували нові системні виклики.
Якщо версія прийнятна -- відновлює AX, перевіряє, чи диск в першому FCB коректний, чи крім диску в першому аргументі нічого немає, і, нарешті, чи не пробуємо ми робити SYS на диск, з якого запустилися, точно так, як і в DOS 1.10. Якщо ні, зберігаємо код поточного диску в currentDrive.
Далі перетворюємо код диску в його літеру (додавши 40h --- див. коментар в коді) і зберігаємо її в дві стрічки, одну довгу (літера диску+":/"+64 порожніх байти), одну коротку (літера диску+":/"+\0 -- символ кінця С-стрічки). Після цього зберігаємо поточний шлях (отриманий викликом AH=47h/INT 21h, "GET CURRENT DIRECTORY") у нулі великої стрічки, яка, таким чином, міститиме повний поточний шлях на момент запуску програми. Потім --- перейти за шляхом, вказаним у короткій стрічці, тобто --- в корінь поточного диску.
Наступні кроки абсолютно такі ж, як і для DOS 1.10 --- відкрити IBMBIO.COM i IBMDOS.COM, використовуючи FCB, задані в коді, якщо їх немає --- попросити вставити системний диск. Мітка AskToInsertSysDisk знаходиться перед перевіркою коректності диску в FCB-1, ефективно запускаючи всі дії програми, окрім перевірки версії, заново. Далі, абсолютно так само, як і раніше, читаються обидва файли, (єдине, що читати максимум 4000h і 5000h відповідно, проти 8000h і 2000h в попередній версії). Якщо успішно, як і раніше, переставляємо в FCB диск на цільовий. Код запиту системного диску не змінився. Код читання файлу теж --- він так само зберігає дату, час і розмір файлу після його FCB.
Далі програма змінює поточний каталог цільового диску на кореневий (використовуючи згадану вище коротку стрічку, але змінивши літеру диску).
Подальший код дещо змінився. DTA переставляється на область для DTA по замовчуванню в PSP, шукається, чи є хоч якісь файли на диску (маска -- "*.*"). Пошук здійснюється за допомогою ще одного FCB. Якщо немає -- перейти до запису системних файлів. Якщо якісь файли є --- спробувати відкрити IBMBIO.COM (використовуючи його FCB, із зміненим раніше цільовим диском). Якщо такого не знайдено, повідомити "No room for system on destination disk" і вийти, інакше перевірити, чи є IBMDOS.COM, за його відсутності --- дати це ж повідомлення і завершити програму. В DOS 1.10 аналогічні дії робилися хитріше --- звірялися розміри файлів... Якщо обидва файли знайдено, IBMDOS.COM видаляється, (тільки він) і провалюємося до запису. Функції запису передаються адреси DTA (в DX) і FCB файлу (в BX) --- вона більш цілісна (ІМХО :), ніж у попередній версії, сама переставляє DTA. Крім того, вона перевіряє, чи записано стільки ж байт, скільки було прочитано, якщо менше --- повідомляє те ж "No room for system on destination disk".
На цьому попередня версія закінчувалася, повідомивши "System transferred". Однак наша робить ще дещо. Після виводу повідомлення, відновлює вихідну поточну директорію поточного диску, потім викликає ще одну функцію, яку я умовно назвав WriteBoot.
Ця функція дивиться на Media ID з FAT цільового диску, якщо він відповідає 8-доріжковим дискетам, перезаписує у них boot! Якщо дискета одностороння, береться образ boot-сектора, збережений в коді, якщо двостороння, його BPB спершу коректується. УВАГА! boot-сектор перезаписується, навіть якщо ситуація "No room for system on destination disk" чи "Incompatible system size". Я так розумію, це спроба тихенько зробити старі, до-BPB, дискети сумісними.
Код boot-сектора я дизасемблювати не став, просто лінь, але з тим проблем не мало б бути. Та й, здається, десь в мережі його дизасемблювання траплялося. Однак, якщо цікаво --- пишіть, зробимо! В кінці трохи загадкового коду, який не використовується ніяк, напевне сміття якесь... Також є код виводу ""Incompatible system size", який теж ніде не використовується.
"Документація"
На відміну від попередньої версії, не порівнює розміри системних файлів на вихідному цільовому дисках. Але більш важливі відмінності наступні:
- Визначається поточна директорія диску, з якого запускали програму, зберігається, відновлюється перед завершенням.
- На 8-секторних цільових дискетах записується новий boot-сектор, навіть якщо систему перенести не вдалося.
Про код
Код став ще трішки чіткішим (ІМХО, знову ж таки), а так --- все той же. Далі нас чекає SYS.COM з DOS 2.10.
А поки:
Дякую за увагу!
Немає коментарів:
Дописати коментар