📄 ldlinux.lst
字号:
757 ; Insane hack to expand the superblock to dwords 758 ; 759 expand_super: 760 0000009F 6631C0 xor eax,eax 761 000000A2 8EC0 mov es,ax ; INT 13:08 destroys ES 762 000000A4 BE[0B00] mov si,superblock 763 000000A7 BFB056 mov di,SuperInfo 764 000000AA B110 mov cl,superinfo_size ; CH == 0 765 .loop: 766 000000AC AD lodsw 767 000000AD 4E dec si 768 000000AE 66AB stosd ; Store expanded word 769 000000B0 30E4 xor ah,ah 770 000000B2 66AB stosd ; Store expanded byte 771 000000B4 E2F6 loop .loop 772 773 ; 774 ; Now we have to do some arithmetric to figure out where things are located. 775 ; If Micro$oft had had brains they would already have done this for us, 776 ; and stored it in the superblock at format time, but here we go, 777 ; wasting precious boot sector space again... 778 ; 779 %define Z di-superinfo_size*8-SuperInfo 780 debugentrypt: 781 000000B6 A1DC56 mov ax,[bxFATs] ; Number of FATs (eax<31:16> == 0) 782 000000B9 668B55D8 mov edx,[Z+bxFATsecs] ; Sectors/FAT 783 000000BD 66F7E2 mul edx ; Get the size of the FAT area 784 ; edx <- 0 785 000000C0 660306[1C00] add eax,[bxHidden] ; Add hidden sectors 786 000000C5 66034598 add eax,[Z+bxResSectors] ; And reserved sectors 787 788 000000C9 66A33057 mov [RootDir],eax ; Location of root directory 789 000000CD 66A33457 mov [DataArea],eax ; First data sector 790 000000D1 6650 push eax 791 792 000000D3 668B45B0 mov eax,[Z+bxRootDirEnts] 793 000000D7 C1E005 shl ax,5 ; Size of a directory entry 794 000000DA 8B5D80 mov bx,[Z+bxBytesPerSec] 795 000000DD 01D8 add ax,bx ; Round up, not down 796 000000DF 48 dec ax 797 000000E0 F7F3 div bx ; Now we have the size of the root dir 798 000000E2 A33857 mov [RootDirSize],ax 799 000000E5 A33A57 mov [DirScanCtr],ax 800 000000E8 81C3E10F add bx,trackbuf-31 801 000000EC 895D0C mov [Z+EndofDirSec],bx ; End of a single directory sector 802 000000EF 66014504 add [Z+DataArea],eax 803 000000F3 6658 pop eax ; Reload root directory starting point 804 805 ; 806 ; Now the fun begins. We have to search the root directory for 807 ; LDLINUX.SYS and load the first sector, so we have a little more 808 ; space to have fun with. Then we can go chasing through the FAT. 809 ; Joy!! 810 ; 811 000000F5 6650 sd_nextsec: push eax 812 000000F7 BB0010 mov bx,trackbuf 813 000000FA 53 push bx 814 000000FB E88200 call getonesec 815 000000FE 5E pop si 816 000000FF B90B00 sd_nextentry: mov cx,11 817 00000102 382C cmp [si],ch ; Directory high water mark 818 00000104 741C je kaboom 819 ; This no longer fits... since we'd be dead anyway if there 820 ; was a nonfile named LDLINUX.SYS on the disk, it shouldn't 821 ; matter... 822 ; test byte [si+11],18h ; Must be a file 823 ; jnz sd_not_file 824 00000106 BF[EF01] mov di,ldlinux_name 825 00000109 56 push si 826 0000010A F3A6 repe cmpsb 827 0000010C 5E pop si 828 0000010D 742E je found_it 829 0000010F 83C620 sd_not_file: add si,byte 32 ; Distance to next 830 00000112 3B363C57 cmp si,[EndofDirSec] 831 00000116 72E7 jb sd_nextentry 832 00000118 6658 pop eax 833 0000011A 6640 inc eax 834 0000011C FF0E3A57 dec word [DirScanCtr] 835 00000120 75D3 jnz sd_nextsec 836 ; 837 ; kaboom: write a message and bail out. 838 ; 839 kaboom: 840 00000122 31F6 xor si,si 841 00000124 8ED6 mov ss,si 842 00000126 BC[B0FF] mov sp,StackBuf-4 ; Reset stack 843 00000129 8EDE mov ds,si ; Reset data segment 844 0000012B 668F067800 pop dword [fdctab] ; Restore FDC table 845 00000130 BE[E001] .patch: mov si,bailmsg 846 00000133 E83600 call writestr ; Returns with AL = 0 847 00000136 98 cbw ; AH <- 0 848 00000137 CD16 int 16h ; Wait for keypress 849 00000139 CD19 int 19h ; And try once more to boot... 850 0000013B EBFE .norge: jmp short .norge ; If int 19h returned; this is the end 851 852 ; 853 ; found_it: now we compute the location of the first sector, then 854 ; load it and JUMP (since we're almost out of space) 855 ; 856 found_it: ; Note: we actually leave two words on the stack here 857 ; (who cares?) 858 0000013D 66A1C456 mov eax,[bxSecPerClust] 859 00000141 89C5 mov bp,ax ; Load an entire cluster 860 00000143 660FB75C1A movzx ebx,word [si+26] ; First cluster 861 00000148 891E9257 mov [RunLinClust],bx ; Save for later use 862 0000014C 4B dec bx ; First cluster is "cluster 2" 863 0000014D 4B dec bx 864 0000014E 66F7E3 mul ebx 865 00000151 6603063457 add eax,[DataArea] 866 00000156 BB[0002] mov bx,ldlinux_sys 867 00000159 E82700 call getlinsec 868 0000015C BE[EF01] mov si,bs_magic 869 0000015F BF[1F02] mov di,ldlinux_magic 870 00000162 B91100 mov cx,magic_len 871 00000165 F3A6 repe cmpsb ; Make sure that the bootsector 872 00000167 75B9 jne kaboom ; matches LDLINUX.SYS 873 ; 874 ; Done! Jump to the entry point! 875 ; 876 00000169 E9C800 jmp ldlinux_ent 877 ; 878 ; 879 ; writestr: write a null-terminated string to the console 880 ; This assumes we're on page 0. This is only used for early 881 ; messages, so it should be OK. 882 ; 883 writestr: 884 0000016C AC .loop: lodsb 885 0000016D 20C0 and al,al 886 0000016F 7409 jz .return 887 00000171 B40E mov ah,0Eh ; Write to screen as TTY 888 00000173 BB0700 mov bx,0007h ; Attribute 889 00000176 CD10 int 10h 890 00000178 EBF2 jmp short .loop 891 0000017A C3 .return: ret 892 893 ; 894 ; disk_error: decrement the retry count and bail if zero. 895 ; This gets patched once we have more space to try to 896 ; optimize transfer sizes on broken machines. 897 ; 898 0000017B 4E disk_error: dec si ; SI holds the disk retry counter 899 0000017C 74A4 jz kaboom 900 ; End of patched "call" instruction! 901 0000017E EB33 jmp short disk_try_again 902 903 ; 904 ; getonesec: like getlinsec, but pre-sets the count to 1 905 ; 906 getonesec: 907 00000180 BD0100 mov bp,1 908 ; Fall through to getlinsec 909 910 ; 911 ; getlinsec: load a sequence of BP floppy sector given by the linear sector 912 ; number in EAX into the buffer at ES:BX. We try to optimize 913 ; by loading up to a whole track at a time, but the user 914 ; is responsible for not crossing a 64K boundary. 915 ; (Yes, BP is weird for a count, but it was available...) 916 ; 917 ; On return, BX points to the first byte after the transferred 918 ; block. 919 ; 920 ; The "stupid patch area" gets replaced by the code 921 ; mov bp,1 ; nop ... (BD 01 00 90 90...) when installing with 922 ; the -s option. 923 ; 924 ; This routine assumes CS == DS. 925 ; 926 ; Stylistic note: use "xchg" instead of "mov" when the source is a register 927 ; that is dead from that point; this saves space. However, please keep 928 ; the order to dst,src to keep things sane. 929 ; 930 getlinsec: 931 00000183 668B361857 mov esi,[bxSecPerTrack] 932 ; 933 ; Dividing by sectors to get (track,sector): we may have 934 ; up to 2^18 tracks, so we need to use 32-bit arithmetric. 935 ; 936 00000188 6631D2 xor edx,edx ; Zero-extend LBA to 64 bits 937 0000018B 66F7F6 div esi 938 0000018E 31C9 xor cx,cx 939 00000190 87CA xchg cx,dx ; CX <- sector index (0-based) 940 ; EDX <- 0 941 ; eax = track # 942 00000192 66F7362857 div dword [bxHeads] ; Con
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -