首页
社区
课程
招聘
[原创]X86-64CPU下 开发64位操作系统试验----双进程试验
发表于: 2008-7-1 22:30 11056

[原创]X86-64CPU下 开发64位操作系统试验----双进程试验

2008-7-1 22:30
11056

前一阵在网上翻到一篇介绍如何初始化“长模式”的文章,(文章出处已经记不得了,在此对作者表示感谢)我对文章进行了研究,发现其中有些不对,就仔细阅读了AMD64的技术手册Vol2,也就是系统编程那一卷。然后改正了文章的一些错误,并以此为基础,近一步实现了长模式下的双进程试验。前后4天的文档阅读,到代码修改到调试成功还真是花了不少功夫,也让我对AMD64有了更深入的了解。下面就把我的一些学习心得和大家分享。
    长模式不同于兼容模式,在长模式下所有的代码和数据都是64位编码的,IDT,TSS,段描述符号等数据结构都做了相应的扩展,任务切换,分页的处理等都有了些变化,具体的请大家去看AMD64的手册,下面我就简单说一下我下面的代码。代码从实模式开始运行按如下步骤操作:
    1.关中断,首先利用CPUID检查CPU是否支持长模式,如果不支持则打印信息,然后停机(halt)。
    2.打开A20线,载入32位保护模式下用的GDT和IDT,其中64位模式下的相关数据结构也包含在了此GDT下,包括64位下的0级代码段描述符,0级数据段描述符,3级代码段和数据段描述符,TSS64描述符;32位的IDT里面的中断处理程序什么也不作只是IRETD,因为我们直到最后才会开启中断。设置好数据段和堆栈指针,利用一个长跳转进入32位保护模式,由于GDT里面的设置,我们其实是进入了FLAT模式,呵呵。
    3.在32位模式下我们的主要工作就是初始化4级分页系统。这里我们采用的是PAE-4K每页的分页方式,内存设定为32M,这在bochs2.3.6下面是可以的,配置文件里面设置了32M内存。其中PAE物理地址扩展是进入长模式所必须的,分页也是长模式所必须的。为了简单起见,分页后的虚拟地址和实际的物理地址是一一对应的。64位模式下,页表项是8字节长的,这一点要注意。首先把所有的内存都设为只有0级可以访问。然后又特别开放了32K以后到C0000的内存给RING3,这是因为我们的代码是加载在内存8000地址的,同时我们的RING3代码也会写屏,所以要开发到C0000。这里还要注意,页级别保护是AND运算的,也就是每一级的保护位AND起来才是最后的保护模式。所以,我要把前三级的低3位都置成1,也就是7,而在最后一级上做限制才可以。另外页表系统在1M内存以上,0,1,2级的堆栈指针都在1M以上,这样就防止RING3的代码恶意修改内核的数据了,实现了隔离。另外还设置了两个RING3的RSP指针,我们这里只演示了两个进程。
  4. 分页完成之后,就是开启PAE,开启分页,启动长模式,利用长跳转进入64位代码。此时我们已经进入了纯64位模式了,进入纯64位模式之后我们会在屏幕中间显示一个粉色的L表示成功,而后重新裁入GDT64,IDT64等数据结构,重置选择子等工作。我们还把模式寄存器的值读了出来,可以在调试时看出长模式是ACTIVE的,EFER = 0x00000500。我们还在屏幕中间显示了一个0,这在后面要用到。
  5. 下面就开始安排双进程了,我们这里又两个进程:
    进程1:不断的增加rax,rax已经预先清0,同时做推栈和弹栈,这是测试RING3的堆栈可用。
       .INE:    inc rax
        push rax
        pop  rbx
        nop
        nop
        nop
        nop
       jmp .INE
   
      进程2:在我们前面显示0的地方,轮流显示0~9字符,同时做推栈和弹栈,这是测试RING3的堆栈可用。
     .INE2:  mov al,byte [0xb8060] ;实验
        inc al
        cmp al,0x3a
        jnz  .T1
        mov al,'0'
     .T1:    mov [0xb8060],al        
        push rax
        pop  rcx   
        jmp .INE2   
   
   只是两个简单的进程,大家可以加入更复杂的东西。不过堆栈只预留了4KB。下面开始讲开启RING3进程和进程调度。
6. 我们一直都在RING0工作,现在我们要返回RING3了,我们采用的手段是通过构造中断返回现场来返回,我们压入进程1的代码指针等相关数据结构,把RFLAG的IF位放开,通过IRETQ来返回到RING3.这条指令执行过后,进程1就开始跑了。下面来说调度。要说调度我们先来看64位下的中断处理函数,除了时间中断,其他的中断处理只是简单的返回。我们这里为了简单,依然用IRQ8来处理时间中断。每当中断来临时候,我们首先会把EAX的值DUMP到屏幕上,然后通过一个ctrl变量来指示应该换入哪个进程。我们已经事先在寄存器保存区设置好了进程2的相关量,进程切换是很容易的事情,无非就是保存A进程的相关寄存器,载入B进程的相关寄存器,然后从中断返回。这样在屏幕上大家就可以看见粉色的0~9在不停的翻转,同时右边红色的EAX值也在不停的刷新。在BOCHS中可以发现,EAX的值不是连续的,显示恍惚,那是因为两个进程都用到了RAX,而每次时间中断到来时都会DUMP当前进程的RAX,所以显示会恍惚,这也正显示了进程调度的成功。大家可以在BOCHS中按暂停键来看右边DUMP的数据的变化。  
   好了所有的东西就讲完了。附件里时直接可以在BOCHS下面加载的磁盘镜像。下面的代码是按照FASM格式编写的,产生纯二进制代码,然后由我的载入程序载入到0x8000的。下面是我从BOCHS的log文件中截取的一段:
0001796619i[BIOS ] Booting from 0000:7c00
01699216000p[WGUI ] >>PANIC<< POWER button turned off.我关调了BOCHS
01699216000i[CPU0 ] CPU is in long mode (active)
01699216000i[CPU0 ] CS.d_b = 16 bit
01699216000i[CPU0 ] SS.d_b = 32 bit
01699216000i[CPU0 ] EFER   = 0x00000500
01699216000i[CPU0 ] | RAX=0000000006508920  RBX=0000000006508920
01699216000i[CPU0 ] | RCX=00000000c0000080  RDX=0000000000000000
01699216000i[CPU0 ] | RSP=000000000009ffff  RBP=0000000000007caf
01699216000i[CPU0 ] | RSI=00000000ffff88ca  RDI=00000000001235f8
01699216000i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
01699216000i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
01699216000i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
01699216000i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
01699216000i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df IF tf sf zf AF pf cf
01699216000i[CPU0 ] | SEG selector     base    limit G D
01699216000i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
01699216000i[CPU0 ] |  CS:003b( 0007| 0|  3) 00000000 0000ffff 0 0
01699216000i[CPU0 ] |  DS:0000( 0004| 0|  0) 00000000 000fffff 1 1
01699216000i[CPU0 ] |  SS:0043( 0008| 0|  3) 00000000 000fffff 1 1
01699216000i[CPU0 ] |  ES:0000( 0004| 0|  0) 00000000 000fffff 1 1
01699216000i[CPU0 ] |  FS:0000( 0000| 0|  0) 00000000 000fffff 1 1
01699216000i[CPU0 ] |  GS:0000( 0000| 0|  0) 00000000 000fffff 1 1
01699216000i[CPU0 ] |  MSR_FS_BASE:0000000000000000
01699216000i[CPU0 ] |  MSR_GS_BASE:0000000000000000
01699216000i[CPU0 ] | RIP=0000000000009b44 (0000000000009b44)
01699216000i[CPU0 ] | CR0=0x80000011 CR1=0x0 CR2=0x0000000000000000
01699216000i[CPU0 ] | CR3=0x00120000 CR4=0x00000020
01699216000i[CPU0 ] >> nop  : 90   这是关机时执行的指令

///////////////////////////////////////////////////////////////////////////////////////

USE16
    org 0x8000
       REAL_MODE_STACK_TOP EQU 0x7C00 - 1
    CODE_SEL EQU CODE_DSCR - DUMMY_DSCR   ; code segment selector
    DATA_SEL EQU DATA_DSCR - DUMMY_DSCR   ; data segment selector
   
    LONG_MODE_RSP3   EQU    0xA0000 - 1
    LONG_MODE_RSP31    EQU    0xA0000 - 1 - 4 * 1024
    LONG_MODE_RSP0    EQU    0x120000 - 1
    LONG_MODE_RSP1    EQU    0x120000 - 1 - 4 * 1024
    LONG_MODE_RSP2   EQU    0x120000 - 1 - 8 * 1024
    LONG_MODE_PTE_BASE    = 0x123000
    LONG_MODE_PDE_BASE    = 0x122000
    LONG_MODE_PDPE_BASE    = 0x121000
    LONG_MODE_PML4E_BASE= 0x120000
   
jmp 0x0:CODE16    ; jump to 16 bit code, initialize base enviroment
ALIGN 4
GDTR32    dw GDT_END - GDT - 1
        dd GDT
ALIGN 4
IDTR32    dw IDT32_END - IDT32_START - 1
        dd IDT32_START
        
PRINT_16:
    push ax
    push bx
    push si
.NEW_CHAR:
    lodsb
    or  al, al
    jz  short .EXIT_PRINT_16
    mov ah, 0x0E
    mov bx, 0x0007
    int 0x10
    jmp short .NEW_CHAR
.EXIT_PRINT_16:
    pop si
    pop bx
    pop ax
    ret

MSG_NO_LONG_MODE db 'Current CPU dose not support LONG mode',13,10,0
NO_LONG_MODE:
    cli
    mov si,MSG_NO_LONG_MODE
    call PRINT_16
    hlt
    jmp $   ; halt here

        
; 16 bit main start
CODE16:
    ; initialize 16 bit registers
    cli
    mov ax, cs
    mov ds, ax
    mov es, ax
    xor ax, ax
    mov ss, ax
    mov sp, REAL_MODE_STACK_TOP

    ; check if x64 long mode is supported
    ; AMD document for details about this check
    ; NOTE: I suppose CPU is 386+, maybe I should
    ;   do another check
    mov eax, 0x80000000
    cpuid
    cmp eax, 0x80000000
    jbe NO_LONG_MODE
    mov eax, 0x80000001
    cpuid
    bt  edx, 29
    jnc NO_LONG_MODE
      
    ; prepare for protect mode
    ; load gdtr
    ; enable cr0.pe
    cli
    ; enable A20 gate
   
    in      al,92h
    or      al,00000010b
    out     92h,al
               
    mov  ebx, IDTR32
    lidt [ebx]
    mov  ebx, GDTR32
    lgdt [ebx]
    mov  eax, cr0
    or   eax, 1
    mov  cr0, eax

    mov bx, DATA_SEL
    mov ds, bx
    mov es, bx
    mov fs, bx
    mov gs, bx
    mov ss, bx
    mov esp, 0x7C00 - 1
   
    ; make a far jump to enter protect mode
    db 0xEA
    dw CODE32
    dw CODE_SEL

;--------------- PROTECT MODE ----------
;................  FOR protect mode  ...................   
ALIGN 16
GDT:
DUMMY_DSCR    dw 0
            dw 0
            dw 0
            dw 0    ; reserved by i386 CPU

CODE_DSCR    dw 0xFFFF
            dw 0x0000
            db 0x00
            db 0x9A
            db 0xCF
            db 0x00

DATA_DSCR    dw 0xFFFF
            dw 0x0000
            db 0x00
            db 0x92
            db 0xCF
            db 0x00
                        
    CODE64_SELECTOR        =    .CODE_DESCRIPTOR - GDT
    .CODE_DESCRIPTOR    dw 0xFFFF
                        dw 0x0000
                        db 0x00
                        db 0x9A
                        db 0x20
                        db 0x00
                        
    DATA64_SELECTOR        =    .DATA_DESCRIPTOR - GDT
    .DATA_DESCRIPTOR    dw 0xFFFF
                        dw 0x0000
                        db 0x00
                        db 0x92
                        db 0xCF
                        db 0x00
                        
    TSS64_SELECTOR        =    .TSS_DESCRIPTOR - GDT
    .TSS_DESCRIPTOR        dw TSS64_END - TSS64 - 1
                        dw TSS64
                        db 0x00
                        db 0x89        ; available TSS
                        db 0x80
                        db 0x00
                        dd 0x00000000
                        dd 0x00000000
   CODE64_SELECTOR3        =    .CODE_DESCRIPTOR3 - GDT+3
    .CODE_DESCRIPTOR3    dw 0xFFFF
                        dw 0x0000
                        db 0x00
                        db 0xfA  ;3级代码段
                        db 0x20
                        db 0x00                     

DATA64_SELECTOR3        =    .DATA_DESCRIPTOR3 - GDT+3
    .DATA_DESCRIPTOR3    dw 0xFFFF
                        dw 0x0000
                        db 0x00
                        db 0xf2
                        db 0xCF
                        db 0x00                        
GDT_END:

ALIGN 16
IDT32_START:
    rept 256 {
        dw PROTECT_MODE_EXCEPTION_HANDLE
        dw CODE_SEL
        db 0x00
        db 0x8E
        dw 0x0000
    }
IDT32_END:

;---------- FOR LONG MODE -----------
ALIGN 4
GDTR64    dw GDT_END - GDT - 1
        dq GDT
        
IDTR64    dw IDT64_END - IDT64 - 1
        dq IDT64

ALIGN 16
TSS64:
    dd 0    ; reserved, ingore
    dq LONG_MODE_RSP0
    dq LONG_MODE_RSP1
    dq LONG_MODE_RSP2
    dq 0    ; reserved
    times 7 dq LONG_MODE_RSP0
    dq 0
    dw 0
    dw $ + 2
    db 0xff
TSS64_END:

ALIGN 16
IDT64:
    rept 8 {
        dw LONG_MODE_EXCEPTION_HANDLE1
        dw CODE64_SELECTOR
        db 0x00
        db 0x8E
        dw 0x0000
        dd 0x00000000
        dd 0x00000000
    }
    ;时钟中断
        dw LONG_MODE_EXCEPTION_HANDLE
        dw CODE64_SELECTOR
        db 0x00
        db 0x8E
        dw 0x0000
        dd 0x00000000
        dd 0x00000000
    rept 247 {
        dw LONG_MODE_EXCEPTION_HANDLE1
        dw CODE64_SELECTOR
        db 0x00
        db 0x8E
        dw 0x0000
        dd 0x00000000
        dd 0x00000000
    }        
IDT64_END:

USE32

CODE32:
;初始化PML4E
    mov edi,LONG_MODE_PML4E_BASE
    mov [edi],dword LONG_MODE_PDPE_BASE+7
    add edi,4
    xor ebx,ebx
    mov [edi],ebx
    add edi,4
    mov ecx,511
.NPML:   
    mov [edi],ebx
    add edi,4
    mov [edi],ebx
    add edi,4
    loop .NPML

;初始化PDPE   
    mov [edi],dword LONG_MODE_PDE_BASE+7
    add edi,4
    mov [edi],ebx
    add edi,4
    mov ecx,511
.NPDE:
    mov [edi],ebx
    add edi,4
    mov [edi],ebx
    add edi,4
    loop .NPDE        
   
;初始化PDE   
    mov eax,LONG_MODE_PTE_BASE+7
    mov [edi],eax
    add edi,4
    mov edi,ebx
    add edi,4
    mov ecx,15
.NPTE:
    add eax,0x1000
    mov [edi],eax
    add edi,4
    mov edi,ebx
    add edi,4   
    loop .NPTE
    mov ecx,512-16
.NPTE1:   
    mov [edi],ebx
    add edi,4
    mov [edi],ebx
    add edi,4
    loop .NPTE1

;初始化PTE   
   mov edi,LONG_MODE_PTE_BASE
   mov eax, 1
   mov ecx,512*16
.NPP:   
   mov [edi],eax
   add edi,4
   mov [edi],ebx
   add edi,4
   add eax,0x1000
   loop .NPP
   
   ;保留前32k内存,开放32K以后到C0000之前的内存给ring3
   mov edi,LONG_MODE_PTE_BASE+0x8*8
   mov eax, 0x8*0x1000+7
   mov ecx, 183
.NP2:   
   mov [edi],dword eax
   add eax,0x1000
   add edi,8   
   loop .NP2

   
    mov eax, cr4
    bts eax, 5
    mov cr4, eax

    mov eax, LONG_MODE_PML4E_BASE
    mov cr3, eax
   
    mov ecx, 0xC0000080
    rdmsr
    bts eax, 8
    wrmsr

    mov eax, cr0
    and eax, 0x1FFFFFFF
    bts eax, 31
    mov cr0, eax
   
    db 0xEA
    dd CODE64
    dw CODE64_SELECTOR
                  
PROTECT_MODE_EXCEPTION_HANDLE:
    iretd
   
; Dump eax to screen
HEX_TABLE    db '0', '1', '2', '3', '4', '5', '6', '7'
            db '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'

   
USE64
LONG_MODE_EXCEPTION_HANDLE1:
    iretq

CODE64:
    mov rax, DATA64_SELECTOR
    mov ds, ax
    mov es, ax
    xor ax,ax
    mov ss, ax
    mov fs, ax
    mov gs, ax
    mov rsp, LONG_MODE_PML4E_BASE - 1
    mov rbx, GDTR64
    lgdt [rbx]
    mov rbx, IDTR64
    lidt [rbx]
         
    mov ax, TSS64_SELECTOR
    ltr ax
   
    mov rax, LONG_MODE_PML4E_BASE
    mov cr3, rax
   
    mov [0xB8050], byte 'L'
    mov [0xB8051], byte 13
   
    mov [0xB8060], byte '0'
    mov [0xB8061], byte 13
   
    mov rcx, 0xC0000080
    rdmsr  
    xor rax,rax         
    mov [srip],.INE2
    push DATA64_SELECTOR3
    push LONG_MODE_RSP3
    pushfq
    pop rbx
    bts rbx,9
    push rbx
    push CODE64_SELECTOR3
    push .INE
    iretq
   
   .INE:    inc rax
    push rax
    pop  rbx
    nop
    nop
    nop
    nop
jmp .INE
   
   
.INE2:  mov al,byte [0xb8060] ;实验
        inc al
        cmp al,0x3a
        jnz  .T1
        mov al,'0'
.T1:    mov [0xb8060],al        
        push rax
        pop  rcx   
        jmp .INE2   
        
SAVEREG:
;第二个进程的参数
          srax dq 0
          srbx dq 0
          srcx dq 0
          srdx dq 0
          srbp dq 0
          srsi dq 0
          srdi dq 0
          srsp dq LONG_MODE_RSP31
          sr8  dq 0
          sr9  dq 0
          sr10 dq 0
          sr11 dq 0
          sr12 dq 0
          sr13 dq 0
          sr14 dq 0
          sr15 dq 0
          srflg dq 0x246  
          srip  dq 0
;第一个进程的参数
          srax1 dq 0
          srbx1 dq 0
          srcx1 dq 0
          srdx1 dq 0
          srbp1 dq 0
          srsi1 dq 0
          srdi1 dq 0
          srsp1 dq 0
          sr81  dq 0
          sr91  dq 0
          sr10_1 dq 0
          sr11_1 dq 0
          sr12_1 dq 0
          sr13_1 dq 0
          sr14_1 dq 0
          sr15_1 dq 0
          srflg_1 dq 0  
          srip_1  dq 0
ctrl dd 0                  
LONG_MODE_EXCEPTION_HANDLE:
    call DUMP_RAX
    push rax
    mov al,20h
    out 20h,al
    mov eax,[ctrl]
    or eax, eax
    jz .TASK2 ;应该换出入第二个进程
.TASK1:
    dec [ctrl]
    pop [srax]
    mov [srbx], rbx
    mov [srcx], rcx
    mov [srdx], rdx
    mov [srbp], rbp
    mov [srsi], rsi
    mov [srdi], rdi
    mov [sr8],  r8  
    mov [sr9],  r9   
    mov [sr10], r10
    mov [sr11], r11
    mov [sr12], r12
    mov [sr13], r13
    mov [sr14], r14
    mov [sr15], r15
    pop [srip]
    pop rax
    pop [srflg]
    pop [srsp]
    push [srsp1]
    push [srflg_1]
    push rax
    push [srip_1]
    mov rax, [srax1]
    mov rbx, [srbx1]
    mov rcx, [srcx1]
    mov rdx, [srdx1]
    mov rbp, [srbp1]
    mov rsi, [srsi1]
    mov rdi, [srdi1]
    mov r8,  [sr81]  
    mov r9,  [sr91]   
    mov r10, [sr10_1]
    mov r11, [sr11_1]
    mov r12, [sr12_1]
    mov r13, [sr13_1]
    mov r14, [sr14_1]
    mov r15, [sr15_1]            
    iretq            
.TASK2:   
    inc [ctrl]
    pop [srax1]
    mov [srbx1], rbx
    mov [srcx1], rcx
    mov [srdx1], rdx
    mov [srbp1], rbp
    mov [srsi1], rsi
    mov [srdi1], rdi
    mov [sr81],  r8  
    mov [sr91],  r9   
    mov [sr10_1], r10
    mov [sr11_1], r11
    mov [sr12_1], r12
    mov [sr13_1], r13
    mov [sr14_1], r14
    mov [sr15_1], r15
    pop [srip_1]
    pop rax
    pop [srflg_1]
    pop [srsp1]
    push [srsp]
    push [srflg]
    push rax
    push [srip]     
    mov rax, [srax]
    mov rbx, [srbx]
    mov rcx, [srcx]
    mov rdx, [srdx]
    mov rbp, [srbp]
    mov rsi, [srsi]
    mov rdi, [srdi]
    mov r8,  [sr8]  
    mov r9,  [sr9]   
    mov r10, [sr10]
    mov r11, [sr11]
    mov r12, [sr12]
    mov r13, [sr13]
    mov r14, [sr14]
    mov r15, [sr15]         
    iretq
DUMP_RAX:
    push rax
    push rbx
    push rcx
    push rdx
   
    mov ebx, 0xB8000 + 2 * ( 0 * 25 + 80 - 10)
    mov dh, 0xC
    mov dl, '0'
    mov [ebx], dx
    inc ebx
    inc ebx

    mov dl, 'x'
    mov [ebx], dx
    inc ebx
    inc ebx
   
    mov ecx, eax
    shr ecx, 28
    mov dl, byte [HEX_TABLE + ecx]
    mov [ebx], dx
    inc ebx
    inc ebx
   
    mov ecx, eax
    shr ecx, 24
    and ecx, 0x0000000F
    mov dl, byte [HEX_TABLE + ecx]
    mov [ebx], dx
    inc ebx
    inc ebx
   
    mov ecx, eax
    shr ecx, 20
    and ecx, 0x0000000F
    mov dl, byte [HEX_TABLE + ecx]
    mov [ebx], dx
    inc ebx
    inc ebx

    mov ecx, eax
    shr ecx, 16
    and ecx, 0x0000000F
    mov dl, byte [HEX_TABLE + ecx]
    mov [ebx], dx
    inc ebx
    inc ebx

    mov ecx, eax
    shr ecx, 12
    and ecx, 0x0000000F
    mov dl, byte [HEX_TABLE + ecx]
    mov [ebx], dx
    inc ebx
    inc ebx

    mov ecx, eax
    shr ecx, 8
    and ecx, 0x0000000F
    mov dl, byte [HEX_TABLE + ecx]
    mov [ebx], dx
    inc ebx
    inc ebx

    mov ecx, eax
    shr ecx, 4
    and ecx, 0x0000000F
    mov dl, byte [HEX_TABLE + ecx]
    mov [ebx], dx
    inc ebx
    inc ebx
   
    mov ecx, eax
    and ecx, 0x0000000F
    mov dl, byte [HEX_TABLE + ecx]
    mov [ebx], dx
   
    pop rdx
    pop rcx
    pop rbx
    pop rax
    ret
   

////////////////////////////////////////////////
欢迎大家有空到我的博客:http://blog.sina.com.cn/tigerdeng 来逛逛啊。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 7
支持
分享
最新回复 (5)
雪    币: 1004
活跃值: (75)
能力值: ( LV9,RANK:570 )
在线值:
发帖
回帖
粉丝
2
终于抢到沙发了,好文,顶!
2008-7-2 20:35
0
雪    币: 7115
活跃值: (639)
能力值: (RANK:1290 )
在线值:
发帖
回帖
粉丝
3
好文。。。 64位的汇编。。。
2008-7-2 20:50
0
雪    币: 116
活跃值: (220)
能力值: ( LV12,RANK:370 )
在线值:
发帖
回帖
粉丝
4
学习。。。。
2008-7-2 21:02
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
哦 好东东!
2008-9-13 17:42
0
雪    币: 609
活跃值: (237)
能力值: ( LV12,RANK:441 )
在线值:
发帖
回帖
粉丝
6
清晰的向下兼容特性……真搞不明白Vista怎么运行16位的程序……
2008-9-13 20:26
0
游客
登录 | 注册 方可回帖
返回
//