China DOS Union

-- Unite DOS · Advance DOS · Grow DOS --

Union site: www.cn-dos.net Forum site: www.cn-dos.net/forum
DOS stands for freedom, openness and progress. Let us work hard, learn from the openness and GNU spirit of FreeDOS and Linux, and together build and grow a free GNU GPL world!

中国DOS联盟论坛
The time now is 2026-08-12 20:13
中国DOS联盟论坛 » DOS学习入门 & 精彩文章 (教学室) » [Repost] Windows 98 Boot Code Analysis Actually Just the Master Boot Record DigestII View 13,162 Replies 1
Original Poster Posted 2008-12-05 09:29 ·  中国 江西 吉安 电信
版主
★★★★
Credits 7,296
Posts 1,628
Joined 2002-10-16 12:00
23-year member
UID 10
Gender Male
Status Offline
Explanation: The hard disk master boot record is independent of the operating system, yet closely related to it -- in many cases it is generated by
; tools provided by the operating system (the exception is when you use other partitioning tools, but then what
; operating system do they run under? ;().
;
; If you have installed Windows 98 (I currently cannot get access to the master boot record under 95; I can’t very well reinstall my
; system with 95, can I?) as your operating system, then the master boot record on your machine is already greatly different from before. Through the analysis below
; you will surely gain some understanding of why Windows 98 changed the master boot record -- it has already begun to support extended Int13h
; ! And the programming techniques in this master boot record are even more something we should learn from.
;
; The master boot record includes two parts: code and data. After it is loaded into memory by the BIOS interrupt Int19h, it gains control. The most important part of the data
; section is of course the partition table! Becoming thoroughly familiar with the master boot record can help us understand the system boot process,
; handle boot failures caused by damage to the master boot record, eliminate boot-type computer viruses, and moreover allow us to
; modify the master boot record to complete the tasks we want: such as multi-booting, adding a soft lock to the system, etc...
;
; The BIOS interrupt always loads the contents of the sector where the master boot record resides (head 0, track 0, sector 1 of the hard disk) (including code and data)
; into the memory area starting at 0000:7C00, then checks whether the last two bytes of that sector’s contents are “AA55”.
; If not, then sorry, Int19h will not hand control over to the master boot record; if so, only then can the following master boot record
; obtain control (Int19 transfers control through a jump instruction):
;
; The master boot record in binary form:
0000:0600 33 C0 8E D0 BC 00 7C FB-50 07 50 1F FC BE 1B 7C 3.....|.P.P....|
0000:0610 BF 1B 06 50 57 B9 E5 01-F3 A4 CB BE BE 07 B1 04 ...PW...........
0000:0620 38 2C 7C 09 75 15 83 C6-10 E2 F5 CD 18 8B 14 8B 8,|.u...........
0000:0630 EE 83 C6 10 49 74 16 38-2C 74 F6 BE 10 07 4E AC ....It.8,t....N.
0000:0640 3C 00 74 FA BB 07 00 B4-0E CD 10 EB F2 89 46 25 <.t...........F%
0000:0650 96 8A 46 04 B4 06 3C 0E-74 11 B4 0B 3C 0C 74 05 ..F...<.t...<.t.
0000:0660 3A C4 75 2B 40 C6 46 25-06 75 24 BB AA 55 50 B4 :.u+@.F%.u$..UP.
0000:0670 41 CD 13 58 72 16 81 FB-55 AA 75 10 F6 C1 01 74 A..Xr...U.u....t
0000:0680 0B 8A E0 88 56 24 C7 06-A1 06 EB 1E 88 66 04 BF ....V$.......f..
0000:0690 0A 00 B8 01 02 8B DC 33-C9 83 FF 05 7F 03 8B 4E .......3.......N
0000:06A0 25 03 4E 02 CD 13 72 29-BE 2D 07 81 3E FE 7D 55 %.N...r).-..>.}U
0000:06B0 AA 74 5A 83 EF 05 7F DA-85 F6 75 83 BE 1A 07 EB .tZ.......u.....
0000:06C0 8A 98 91 52 99 03 46 08-13 56 0A E8 12 00 5A EB ...R..F..V....Z.
0000:06D0 D5 4F 74 E4 33 C0 CD 13-EB B8 00 00 80 49 12 00 .Ot.3........I..
0000:06E0 56 33 F6 56 56 52 50 06-53 51 BE 10 00 56 8B F4 V3.VVRP.SQ...V..
0000:06F0 50 52 B8 00 42 8A 56 24-CD 13 5A 58 64 10 72 PR..B.V$..ZX.d.r
0000:0700 0A 40 75 01 42 80 C7 02-E2 F7 F8 5E C3 EB 74 B7 .@u.B......^..t.
0000:0710 D6 C7 F8 B1 ED CE DE D0-A7 00 BC D3 D4 D8 B2 D9 ................
0000:0720 D7 F7 CF B5 CD B3 CA B1-B3 F6 B4 ED 00 4D 69 73 .............Mis
0000:0730 73 69 6E 67 20 6F 70 65-72 61 74 69 6E 67 20 73 sing operating s
0000:0740 79 73 74 65 6D 00 00 00-00 00 00 00 00 00 00 00 ystem...........
0000:0750 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0760 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0770 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0780 00 00 00 8B FC 1E 57 8B-F5 CB 00 00 00 00 00 00 ......W.........
0000:0790 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:07A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:07B0 00 00 00 00 00 00 00 00-86 D8 00 00 00 00 80 01 ................
0000:07C0 01 00 06 3F 3F FD 3F 00-00 00 41 A0 0F 00 00 00 ...??.?...A.....
0000:07D0 01 FE 05 3F FF FE 80 A0-0F 00 C0 4F 2F 00 00 00 ...?.......O/...
0000:07E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:07F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 55 AA ..............U.
;
; Disassembly result
;
; 0000:7C00~0000:7C1A: Initialize each segment register and the stack pointer. Finally, relocate the master boot record in memory, freeing the memory space it occupies
; for loading the partition boot record.
0000:7C00 33C0 XOR AX,AX ;clear AX register to 0
0000:7C02 8ED0 MOV SS,AX ;SS=0
0000:7C04 BC007C MOV SP,7C00 ;load the stack pointer -- SS:SP=0000:7C00
0000:7C07 FB STI ;enable interrupts (when loading the stack pointer, interrupts should be disabled to avoid stack confusion caused by hardware interrupts)
0000:7C08 50 PUSH AX ;
0000:7C09 07 POP ES ;load extra data segment register ES=0
0000:7C0A 50 PUSH AX ;
0000:7C0B 1F POP DS ;load data segment register DS=0
0000:7C0C FC CLD ;specify that the following string operations are forward string operations
0000:7C0D BE1B7C MOV SI,7C1B ;source pointer
0000:7C10 BF1B06 MOV DI,061B ;destination pointer
0000:7C13 50 PUSH AX ;
0000:7C14 57 PUSH DI ;look at 0000:7C1A -- construct a jump
0000:7C15 B9E501 MOV CX,01E5 ;
0000:7C18 F3 REPZ ;
0000:7C19 A4 MOVSB


; ;transfer CX bytes starting at 0000:7C1B to the area starting at 0000:061B
0000:7C1A CB RETF ;jump to 0000:061B (this is a trick jump)
;
; For the sake of clarity, the addresses below are given as the actual runtime addresses.
; 0000:061B~0000:062B: Perform a preliminary check on the partition table. Once a partition table entry status byte is detected as greater than or equal to 80h, it passes (of
; course, before this, if the status byte of a partition table entry is detected as less than 80h, it turns to error handling. Of course, if the status bytes of all four partition entries
; are zero, the master boot record will call the BIOS-ROM INT 18h, display the "PRESS A KEY TO REBOOT" message, and wait for your operation.
0000:061B BEBE07 MOV SI,07BE ;SI points to the first partition table entry; at this time CX=0
0000:061E B104 MOV CL,04 ;the partition table has four entries in total
0000:0620 382C CMP [SI],CH ;
0000:0622 7C09 JL 062D ;greater than or equal to 80h transfers [note the JL instruction: jump if (SF xor OF)=1]
0000:0624 7515 JNZ 063B ;if not 0, then [SI] must be less than 80h, so it can only go to error handling!
0000:0626 83C610 ADD SI,+10 ;if zero, check the next entry
0000:0629 E2F5 LOOP 0620 ;check the next entry
0000:062B CD18 INT 18 ;if the status bytes of all four entries are 0, then the system has no choice but to call INT 18h!
;
; 0000:062D~0000:0639: Check the remaining partition table entries -- the status byte must be zero, otherwise display the error message “Invalid partition table” and
; then hang! Come on, did Microsoft get this wrong or not? Why use a Chinese prompt message? Really fucking stupid in a cute way!
; There is also a little BUG here. The previous pass principle is that as long as the status byte is greater than or equal to 80h, then what if this byte is a value such as A0h or E5h
; ? Hehe, this boot record will regard all of them as valid bootable partitions!
0000:062D 8B14 MOV DX,[SI] ;prepare to read the partition boot record: head number → DH, drive number → DL
0000:062F 8BEE MOV BP,SI ;SI→BP, save the pointer to the bootable partition table entry
;
0000:0631 83C610 ADD SI,+10 ;the remaining partition table entries still need to be checked
0000:0634 49 DEC CX ;
0000:0635 7416 JZ 064D ;if CX=0 then the check has passed smoothly, transfer to continue
0000:0637 382C CMP [SI],CH ;
0000:0639 74F6 JZ 0631 ;zero, a legal entry, then check the next entry
;
; 0000:063B~0000:064B: Execute error handling -- after reporting the error message, hang
0000:063B BE1007 MOV SI,0710 ;error message string offset+1→SI
0000:063E 4E DEC SI ;SI-1→SI
0000:063F AC LODSB ;SI+1→SI
0000:0640 3C00 CMP AL,00 ;
0000:0642 74FA JZ 063E ;AL=0 indicates that one error message has finished displaying, and the system falls into an infinite loop
0000:0644 BB0700 MOV BX,0007 ;character-mode display
0000:0647 B40E MOV AH,0E ;
0000:0649 CD10 INT 10 ;display information by teletype write mode (display only one character)
0000:064B EBF2 JMP 063F ;display the next character, until the end of the prompt message is encountered
;
; 0000:064D~0000:0662: Determine the partition type of the bootable partition, then transfer to the corresponding handler.
0000:064D 894625 MOV [BP+25],AX ;BP=pointer to the first bootable partition table entry; at this time AX=0000h
;use the shortest instruction to clear the two units starting at [BP+25] to zero
;these two units will be used to store intermediate variables
0000:0650 96 XCHG SI,AX ;at this time this is the best instruction choice for clearing SI (only 1 byte), and will serve 0000:06B8
0000:0651 8A4604 MOV AL,[BP+04] ;fetch partition type (in this example it is “06” -- FAT16 primary DOS partition)
0000:0654 B406 MOV AH,06 ;prepare to change the partition type in case extended INT 13h cannot be used
0000:0656 3C0E CMP AL,0E ;0Eh: FAT16 primary DOS partition that needs to be accessed with extended INT 13h
0000:0658 7411 JZ 066B ;0Eh type partition transfers to 066Bh
0000:065A B40B MOV AH,0B ;
0000:065C 3C0C CMP AL,0C ;0Ch: FAT32 partition that needs to be accessed with extended INT 13h
0000:065E 7405 JZ 0665 ;0Ch type partition transfers to 0665h for preliminary preprocessing
0000:0660 3AC4 CMP AL,AH ;0Bh: FAT32 partition that can be accessed with traditional INT 13h
0000:0662 752B JNZ 068F ;other types of partitions transfer to 068Fh
;
; 0000:0664~0000:06A1: Perform processing work before reading the partition boot record based on the partition type and the contents of the partition table entry
0000:0664 40 INC AX &nbs

p; ;★★★processing of 0Bh type partitions begins here; the purpose of this instruction is to clear the ZF flag
0000:0665 C6462506 MOV BYTE PTR [BP+25],06 ;★★★processing of 0Ch type partitions begins here
;Why the value 06 is used, I cannot give a self-consistent explanation for the moment; please be patient for a few days.
0000:0669 7524 JNZ 068F ;please note the effect of the above instruction on the ZF flag: 0Bh type partition transfers, 0Ch does not transfer
; The code segment 0000:066B~0000:068C has a chance to execute only when the partition type is 0Ch or 0Eh
0000:066B BBAA55 MOV BX,55AA ;★★★processing of 0Eh type partitions begins here
0000:066E 50 PUSH AX ;
0000:066F B441 MOV AH,41 ;extended INT 13h function, detect whether the BIOS already supports extended INT13h
0000:0671 CD13 INT 13 ;entry parameters: BX=55AAh,DL=drive number,AH=41h
0000:0673 58 POP AX ;after execution, restore AX to 060Eh
0000:0674 7216 JB 068C ;if not supported, transfer
0000:0676 81FB55AA CMP BX,AA55 ;
0000:067A 7510 JNZ 068C ;if extended INT13h is unavailable, also transfer
0000:067C F6C101 TEST CL,01 ;test whether extended disk access is supported
0000:067F 740B JZ 068C ;if not supported, still transfer
; Because there is a great difference between reading the disk by extended INT13h and reading the disk by standard INT13h, the instruction at 0000:0686 modifies the following code to ensure that when
; reading the partition boot sector in extended read mode, it can correctly jump to the corresponding handler.
0000:0681 8AE0 MOV AH,AL ;partition type→AH
0000:0683 885624 MOV [BP+24],DL ;save drive number→[BP+24]
0000:0686 C706A106EB1E MOV WORD PTR [06A1],1EEB ;modify the code at 0000:06A1 to "JMP 06C1"
0000:068C 886604 MOV [BP+04],AH ;note: if extended INT13h cannot be used, then A changes the partition type to 06, but if
;extended INT13h can be used, the original partition type is still kept unchanged
0000:068F BF0A00 MOV DI,000A ;★★★processing of other types of partitions begins here. This instruction initializes the counter
0000:0692 B80102 MOV AX,0201 ;AH: read operation, AL: read the contents of 1 sector
0000:0695 8BDC MOV BX,SP ;SP=7C00→BX, specify the memory offset where the partition boot record is loaded
0000:0697 33C9 XOR CX,CX ;clear CX to zero
0000:0699 83FF05 CMP DI,+05 ;note 5
0000:069C 7F03 JG 06A1 ;if greater, transfer to read the partition boot sector specified by the partition table
0000:069E 8B4E25 MOV CX,[BP+25] ;if less, it proves that the boot sector specified by the partition table that was read has no legal boot record,
;change to read again according to ???; after all, one more choice means one more chance! ;)
; For the items marked ①② below, please note that their addresses are the same, which means that in actual operation only one of the two can exist. But for the convenience of analysis, I
; have listed both for comparison. When reading,千万 don’t take them as two instructions!
①0000:06A1 034E02 ADD CX,[BP+02] ;obtain the cylinder number and physical sector number where the partition boot sector is located
②0000:06A1 EB1E JMP 06C1 ;if the partition type is 0Ch or 0Eh and extended read can be used, execute this instruction
;
; 0000:06A4: Load the partition boot record of the bootable partition into the specified memory area
; Entry parameters: AH=function number, 02 for disk read operation; AL=number of sectors read at one time
; ES:BX=starting address in memory to read into
; CH=low 8 bits of the 10-bit cylinder number; CL: the high two bits are the high two bits of the 10-bit cylinder number, the low 6 bits are the physical sector number
; DH=head number; DL=drive number, the highest bit (i.e. bit 7) is 0 for floppy disk, 1 for hard disk
0000:06A4 CD13 INT 13 ;read the partition boot record into the area starting at 0000:7C00
;
;
0000:06A6 7229 JB 06D1 ;if unsuccessful, transfer
0000:06A8 BE2D07 MOV SI,072D ;error message string offset→SI
0000:06AB 813EFE7D55AA CMP WORD PTR [7DFE],AA55 ;is the partition boot record legal?
0000:06B1 745A JZ 070D ;if legal, transfer (this is the only normal exit of the master boot record)
0000:06B3 83EF05 SUB DI,+05 ;if illegal, prepare to switch to reading another sector
0000:06B6 7FDA JG 0692 ;there is only one chance to switch sectors and read!
;
; 0000:06B8~0000:06BF: Error preprocessing
0000:06B8 85F6 TEST SI,SI ;test whether the SI value is 0; its meaning is to determine which message should be displayed
0000:06BA 7583 JNZ 063F ;if not 0, transfer to error handling and display “Missing operating system”
0000:06BC BE1A07 MOV SI,071A ;error message string offset→SI
0000:06BF EB8A JMP 064B ;transfer to error handling and display “Error loading operating system”
;
; 0000:06C1~0000:06CF: Arrange the entry parameters required for extended read,

then call the extended read subroutine
; This segment of code only has a chance to execute when reading the partition boot record in extended read mode
0000:06C1 98 CBW ;convert byte AL into word AX; after execution, AX contains the number of sectors to read at one time
0000:06C2 91 XCHG CX,AX ;AX→CX, CX→AX; after execution, CX contains the number of sectors to read at one time
0000:06C3 52 PUSH DX ;
0000:06C4 99 CWD ;convert word AX into double word→DX,AX
0000:06C5 034608 ADD AX,[BP+08] ;
0000:06C8 13560A ADC DX,[BP+0A] ;after execution, DX:AX=LBA absolute physical sector number
0000:06CB E81200 CALL 06E0 ;call the extended read subroutine
0000:06CE 5A POP DX ;
0000:06CF EBD5 JMP 06A6 ;
;
; 0000:06D1~0000:06D8 handling when loading the partition boot record fails
0000:06D1 4F DEC DI ;counter minus 1
0000:06D2 74E4 JZ 06B8 ;if all five disk reads fail, transfer to error handling (note that SI=0 at this time)
0000:06D4 33C0 XOR AX,AX ;set function number
0000:06D6 CD13 INT 13 ;reset disk system
0000:06D8 EBB8 JMP 0692 ;read again
;
;
0000:06DA 00 00 80 49 12 00 ...I..
;
; 0000:06E0~0000:070C: Subroutine for reading the partition boot record using the extended INT 13h function
; When called, SP=7BFE. This program constructs a disk address packet by pushing registers onto the stack; please pay attention and appreciate it. Also, the instruction at 0000:06FC
; releases almost all the stack space occupied by this segment of the program in one go. The ingenuity of the conception is absolutely something we need to learn from!
; Therefore, when analyzing this segment of the program, one key point should be placed on the changes in the stack.
0000:06E0 56 PUSH SI ;save SI -- note that this push does not construct the disk address packet
0000:06E1 33F6 XOR SI,SI ;clear to zero
0000:06E3 56 PUSH SI ;
0000:06E4 56 PUSH SI ;
0000:06E5 52 PUSH DX ;
0000:06E6 50 PUSH AX ;the above four instructions push the sector LBA number*2 onto the stack
0000:06E7 06 PUSH ES ;push the segment address of the start of the memory target buffer onto the stack
0000:06E8 53 PUSH BX ;push the offset of the start of the memory target buffer onto the stack
0000:06E9 51 PUSH CX ;push the number of sectors read onto the stack
0000:06EA BE1000 MOV SI,0010 ;note that the high 8 bits of SI correspond to the reserved byte of the disk address packet, and must be 0
0000:06ED 56 PUSH SI ;push the disk address packet length onto the stack; after executing this instruction, a packet has been constructed
0000:06EE 8BF4 MOV SI,SP ;specify the disk address packet offset pointer; at this time SP=7BEA
0000:06F0 50 PUSH AX ;save AX
0000:06F1 52 PUSH DX ;save DX
0000:06F2 B80042 MOV AX,4200 ;set extended read function number
0000:06F5 8A5624 MOV DL,[BP+24] ;fetch drive number, refer to 0000:0683
; Entry parameters: AH=function number, 02 for disk read operation; DL=drive number
; DS:SI=16-byte disk address packet -- byte 0: packet length (fixed at 10h); byte 1: reserved, must be 0;
; bytes 2, 3: number of sectors read; bytes 4~5: offset of the start of the memory target buffer;
; bytes 6~7: segment address of the start of the memory target buffer; bytes 8~15: sector LBA number
; Exit parameters: if successful AH=0; if error AH=error code
0000:06F8 CD13 INT 13 ;execute extended read operation
0000:06FA 5A POP DX ;
0000:06FB 58 POP AX ;
0000:06FC 8D6410 LEA SP,[SI+10] ;7BEA+10h=7BFA→SP (note that this takes the offset, not the contents of the unit)
0000:06FF 720A JB 070B ;if extended read is unsuccessful, transfer
0000:0701 40 INC AX ;
0000:0702 7501 JNZ 0705 ;
0000:0704 42 INC DX ;DX is incremented only when adding 1 to AX overflows (for example 0FFFFh+1)
0000:0705 80C702 ADD BH,02 ;adjust BX, making the offset increase by 512 bytes (exactly one sector)
0000:0708 E2F7 LOOP 0701 ;I still do not understand the real intention of the code segment 0701~0708!
0000:070A F8 CL





C ;
0000:070B 5E POP SI ;
0000:070C C3 RET ;
;
; 0000:070D: relay jump
0000:070D EB74 JMP 0783 ;
;
; 070F~0745 are error messages! It is indeed the master boot record generated by Chinese Windows98, so I want to especially
; “thank” Microsoft, that stupid cunt. It must have been so hard for it to actually express the first two messages in Chinese! Unfortunately, when it really needs to be displayed,
; only a ghost could understand what it is!!! Fuck! -- Are they messing with us!?
; 070F~0718: Chinese message “Invalid partition table”
; 071A~072B: Chinese message “Error loading operating system”
; 072D~0744: English message “Missing operating system”
0000:070F B7 .
0000:0710 D6 C7 F8 B1 ED CE DE D0-A7 00 BC D3 D4 D8 B2 D9 ................
0000:0720 D7 F7 CF B5 CD B3 CA B1-B3 F6 B4 ED 00 4D 69 73 .............Mis
0000:0730 73 69 6E 67 20 6F 70 65-72 61 74 69 6E 67 20 73 sing operating s
0000:0740 79 73 74 65 6D 00 00 00-00 00 00 00 00 00 00 00 system..........
0000:0750 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0760 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0770 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0780 00 00 00 ...
;
; 0000:0783~0000:0789: transfer of control
0000:0783 8BFC MOV DI,SP ;
0000:0785 1E PUSH DS ;
0000:0786 57 PUSH DI ;construct a jump address
0000:0787 8BF5 MOV SI,BP ;
0000:0789 CB RETF ;hand control over to the partition boot record (0000:7C00)
;
;
0000:078A 00 00 00 00 00 00 ......
0000:0790 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:07A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
;
; What are the four bytes 07B8~07BB used for? (these four bytes differ on different machines)
; 07BE~07FD is the partition table, containing four partition table entries (each entry is 10h bytes)
0000:07B0 00 00 00 00 00 00 00 00-86 D8 00 00 00 00 80 01 ................
0000:07C0 01 00 06 3F 3F FD 3F 00-00 00 41 A0 0F 00 00 00 ...??.?...A.....
0000:07D0 01 FE 05 3F FF FE 80 A0-0F 00 C0 4F 2F 00 00 00 ...?.......O/...
0000:07E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:07F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 55 AA ..............U.
*1: Because physical sector numbers always start from 1
*2: From this it can be seen that even when using the LBA extended read function, the master boot record still limits the partition boot sector to being before the LBA absolute physical sector
0FFFFFFFFh before it is possible to boot the system from that partition!
ko20010214
=================================
大功告成,打个Kiss!
ko20010214@MSN.com
神州优雅Q300C
Intel CeleronM 370处理器 | 256MbDDR内存
40G硬盘 | USB2.0 | IEEE 1394
13.3 ' WXGA 宽屏(16:10) | COMBO光驱
10/100M网卡 | 四合一读卡器
Floor 2 Posted 2008-12-14 17:02 ·  中国 北京 鹏博士BGP
中级用户
★★
Credits 256
Posts 133
Joined 2008-09-29 13:30
17-year member
UID 126984
Gender Male
Status Offline
Thanks to the landlord's information, I finally understand.
Forum Jump: