演示任务切换的实例(实例五)--RadASM编译

以下代码用RadASM编译(其实也是用MASM编译的),BOCHS调试成功。

红色字体是经过增加或修改的,否则不能编译成功,相信会节省初学者不少精力。

INCLUDE         386SCD.INC
;----------------------------------------------------------------------------


GDTSEG          SEGMENT PARA USE16                ;全局描述符表数据段(16位)
;----------------------------------------------------------------------------
                ;全局描述符表
GDT             LABEL   BYTE
                ;空描述符
DUMMY           DESCRIPTOR    <>
                ;规范段描述符及选择子
Normal          DESCRIPTOR    <0ffffh,0,0,ATDW,0>
Normal_Sel      =       Normal-GDT
                ;视频缓冲区段描述符(DPL=3)及选择子
EFFGDT          LABEL   BYTE
               ;演示任务的任务状态段描述符及选择子
DemoTSS         DESCRIPTOR    <DemoTSSLen-1,DemoTSSSeg,,AT386TSS,>
DemoTSS_Sel     =       DemoTSS-GDT


                ;演示任务的局部描述符表段的描述符及选择子
DemoLDTab       DESCRIPTOR    <DemoLDTLen-1,DemoLDTSeg,,ATLDT,>
DemoLDT_Sel     =       DemoLDTab-GDT
 
                ;临时任务的任务状态段描述符及选择子
TempTSS         DESCRIPTOR    <TempTSSLen-1,TempTSSSeg,,AT386TSS+DPL2,>
TempTSS_Sel     =       TempTSS-GDT
                ;临时代码段描述符及选择子
TempCode        DESCRIPTOR    <0ffffh,TempCodeSeg,,ATCE,>
TempCode_Sel    =       TempCode-GDT
               
                ;子程序代码段描述符及选择子
SubR            DESCRIPTOR    <SubRLen32-1,SubRSeg,,ATCE+D32,>
SubR_Sel        =       SubR-GDT+RPL3


; VIDEOBUFF       DESCRIPTOR    <0ffffh,8000h,0bh, ATDW+DPL3,>
VIDEOBUFF DESCRIPTOR<0FFFFH,0,0,0F00H+ATDW+DPL3,0>
Video_SEL = VIDEOBUFF   - GDT
;----------------------------------------------------------------------------


GDNUM           =       ($-EFFGDT)/(SIZE DESCRIPTOR)    ;需处理基地址的描述符个数
GDTLen          =       $-GDT                     ;全局描述符表长度


;----------------------------------------------------------------------------
GDTSEG          ENDS                              ;全局描述符表段定义结束
;----------------------------------------------------------------------------
DemoLDTSeg      SEGMENT PARA USE16                ;局部描述符表数据段(16位)


;----------------------------------------------------------------------------
DemoLDT         LABEL   BYTE                      ;局部描述符表
                ;0级堆栈段描述符(32位段)及选择子
DemoStack0      DESCRIPTOR    <DemoStack0Len-1,DemoStack0Seg,,ATDW+D32,>


DemoStack0_Sel  =       DemoStack0-DemoLDT+TIL
                ;2级堆栈段描述符(32位段)及选择子
DemoStack2      DESCRIPTOR    <DemoStack2Len-1,DemoStack2Seg,,ATDW+DPL2+D32,>


DemoStack2_Sel  =       DemoStack2-DemoLDT+TIL+RPL2
                ;演示任务代码段描述符(32位段,DPL=2)及选择子
DemoCode        DESCRIPTOR    <DemoCodeLen32-1,DemoCodeSeg,,ATCE+DPL2+D32,>


DemoCode_Sel    =       DemoCode-DemoLDT+TIL+RPL2
                ;演示任务数据段描述符(32位段,DPL=3)及选择子
DemoData        DESCRIPTOR    <DemoDataLen32-1,DemoDataSeg,,ATDW+DPL3+D32,>


DemoData_Sel    =       DemoData-DemoLDT+TIL
                ;把LDT作为普通数据段描述的描述符(DPL=2)及选择子
ToDLDT          DESCRIPTOR    <DemoLDTLen-1,DemoLDTSeg,,ATDW+DPL2,>


ToDLDT_Sel      =       ToDLDT-DemoLDT+TIL
                ;把TSS作为普通数据段描述的描述符(DPL=2)及选择子
ToTTSS          DESCRIPTOR    <TempTSSLen-1,TempTSSSeg,,ATDW+DPL2,>


ToTTSS_Sel      =       ToTTSS-DemoLDT+TIL
;----------------------------------------------------------------------------
DemoLDNum       =       ($-DemoLDT)/(SIZE DESCRIPTOR)   ;需处理基地址的LDT描述符数


;----------------------------------------------------------------------------
                ;指向子程序SubRB代码段的调用门(DPL=3)及选择子
ToSubR          GATE    <SubRB32,SubR_Sel,0,AT386CGAT+DPL3,0>
ToSubR_Sel      =       ToSubR-DemoLDT+TIL+RPL2
                ;指向临时任务Temp的任务门(DPL=3)及选择子


ToTempT         GATE    <0,TempTSS_Sel,0,ATTASKGAT+DPL3,0>
ToTempT_Sel     =       ToTempT-DemoLDT+TIL


;----------------------------------------------------------------------------
DemoLDTLen      =       $-DemoLDT
;----------------------------------------------------------------------------
DemoLDTSeg      ENDS                              ;局部描述符表段定义结束
;----------------------------------------------------------------------------
DemoTSSSeg      SEGMENT PARA USE16                ;任务状态段TSS


;----------------------------------------------------------------------------
                DD      0                         ;链接字
                DD      DemoStack0Len             ;0级堆栈指针
                DW      DemoStack0_Sel,0          ;0级堆栈选择子


                DD      0                         ;1级堆栈指针(实例不使用)
                DW      ?,0                       ;1级堆栈选择子(实例不使用)
                
                DD      DemoStack2Len                        ;2级堆栈指针
                DW      DemoStack2_Sel,0                       ;2级堆栈选择子
                DD      0                         ;CR3
                DW      DemoBegin32,0               ;EIP


                DD      0                         ;EFLAGS
                DD      0                         ;EAX
                DD      0                         ;ECX


                DD      0                         ;EDX
                DD      0                         ;EBX
                DD      DemoStack2Len             ;ESP


                DD      0                         ;EBP
                DD      0                         ;ESI
                DD      0b8000h                  ;EDI
                DW      Video_SEL,0               ;ES
                DW      DemoCode_Sel,0            ;CS


                DW      DemoStack2_Sel,0          ;SS
                DW      DemoData_Sel,0            ;DS


                DW      ToDLDT_Sel,0              ;FS
                DW      ToTTSS_Sel,0              ;GS


                DW      DemoLDT_Sel,0             ;LDTR
                DW      0                         ;调试陷阱标志
                DW      $+2                       ;指向I/O许可位图


                DB      0ffh                      ;I/O许可位图结束标志
DemoTSSLen      =       $ - DemoTSSSeg
DemoTSSSeg      ENDS                              ;任务状态段TSS结束


;----------------------------------------------------------------------------




DemoStack0Seg   SEGMENT PARA USE32                ;演示任务0级堆栈段(32位段)
DemoStack0Len   =       1024
                DB      DemoStack0Len DUP(0)


DemoStack0Seg   ENDS                              ;演示任务0级堆栈段结束
;----------------------------------------------------------------------------
DemoStack2Seg   SEGMENT PARA USE32               ;演示任务2级堆栈段(32位段)
DemoStack2Len   =       512


                DB      DemoStack2Len DUP(0)
DemoStack2Seg   ENDS                              ;演示任务2级堆栈段结束
;----------------------------------------------------------------------------
DemoDataSeg     SEGMENT PARA USE32                ;演示任务数据段(32位段)


Message         DB      'Value=',0
DemoDataLen32 equ this word
DemoDataLen     =       $ - DemoDataSeg
DemoDataSeg     ENDS                              ;演示任务数据段结束


;----------------------------------------------------------------------------
SubRSeg         SEGMENT PARA USE32                ;子程序代码段(32位)
                ASSUME  CS:SubRSeg
;----------------------------------------------------------------------------
SubRB32 equ this word
SubRB           PROC    FAR
                push    ebp
                mov     ebp,esp


                pushad                            ;保护现场
                mov     esi,DWORD PTR [ebp+12]    ;从0级栈中取出显示串偏移


                mov     ah,4ah                    ;设置显示属性
                jmp     SHORT SubR2
SubR1:          stosw


SubR2:          lodsb
                or      al,al
                jnz     SubR1
                mov     ah,4eh                    ;设置显示属性


                mov     edx,DWORD PTR [ebp+16]    ;从0级栈中取出显示值


                mov     ecx,8
SubR3:          rol     edx,4
                mov     al,dl


                call    HToASCII
                stosw
                loop    SubR3
                popad
                pop     ebp


                ret     8
SubRB           ENDP
;----------------------------------------------------------------------------
HToASCII        PROC
                and     al,0fh


                add     al,90h
                daa
                adc     al,40h
                daa
                ret
HToASCII        ENDP
SubRLen32 equ this word
SubRLen         =       $ - SubRSeg
SubRSeg         ENDS                              ;子程序代码段结束


;----------------------------------------------------------------------------
DemoCodeSeg     SEGMENT PARA USE32                ;演示任务的32位代码段
                ASSUME  CS:DemoCodeSeg


;----------------------------------------------------------------------------
DemoBegin32 equ this word
DemoBegin :     
                ;把要复制的参数个数置入调用门
                mov     BYTE PTR fs:ToSubR.DCOUNT,2


                ;向2级堆栈中压入参数
                push    DWORD PTR gs:TempTask.TREIP
                push    OFFSET Message
                ;通过调用门调用SubRB


                CALL32  ToSubR_Sel,0
                ;把指向规范数据段描述符的选择子填入临时任务TSS
                ASSUME  DS:TempTSSSeg
                push    gs


                pop     ds
                mov     ax,Normal_Sel
                mov     WORD PTR TempTask.TRDS,ax


                mov     WORD PTR TempTask.TRES,ax
                mov     WORD PTR TempTask.TRFS,ax


                mov     WORD PTR TempTask.TRGS,ax
                mov     WORD PTR TempTask.TRSS,ax


                ;通过任务门切换到临时任务
                JUMP32  ToTempT_Sel,0
       DemoCodeLen32 equ this word
DemoCodeLen     =       $ - DemoCodeSeg
DemoCodeSeg     ENDS                              ;演示任务的32位代码段结束




;----------------------------------------------------------------------------
TempTSSSeg      SEGMENT PARA USE16                ;临时任务的任务状态段TSS


TempTask        TASKSS     <>
                DB      0ffh                      ;I/O许可位图结束标志
TempTSSLen      =       $  
TempTSSSeg      ENDS


;----------------------------------------------------------------------------
TempCodeSeg     SEGMENT PARA USE16                ;临时任务的代码段
                ASSUME  CS:TempCodeSeg
;----------------------------------------------------------------------------


Virtual  :
                mov     ax,TempTSS_Sel            ;装载TR
                ltr     ax


                JUMP16  DemoTSS_Sel,0             ;直接切换到演示任务
         ToReal:
                clts                              ;清任务切换标志
                mov     eax,cr0                   ;准备返回实模式


                and     al,0fffffffeh
                mov     cr0,eax
                JUMP16  <SEG Real>,<OFFSET Real>
TempCodeLEN = $ - TempCodeSeg


TempCodeSeg     ENDS
;============================================================================
RDataSeg        SEGMENT PARA USE16                ;实方式数据段


VGDTR           PDESC   <GDTLen-1,>               ;GDT伪描述符
SPVar           DW      ?                         ;用于保存实方式下的SP
SSVar           DW      ?                         ;用于保存实方式下的SS


RDataSeg        ENDS
;----------------------------------------------------------------------------
RCODESEG        SEGMENT PARA USE16
                ASSUME  CS:RCODESEG,DS:RDataSeg,ES:RDataSeg


;----------------------------------------------------------------------------
Start  :        
; jmp $ ;bochs调试时使用,CTRL+C中断后,set $eip = 2 ,C运行即可。
                mov     ax,RDataSeg
                mov     ds,ax


                cld
                call    INIT_GDT                   ;初始化全局描述符表GDT
                mov     ax,DemoLDTSeg
                mov     fs,ax


                mov     si,OFFSET DemoLDT
                mov     cx,DemoLDNum
                call    INIT_LDT                   ;初始化局部描述符表LDT


                mov     SSVar,ss
                mov     SPVar,sp
                lgdt    FWORD PTR VGDTR           ;装载GDTR并切换到保护方式


                cli
                mov     eax,cr0
                or      al,1


                mov     cr0,eax
                JUMP16  <TempCode_Sel>,<OFFSET Virtual>
Real:           mov     ax,RDataSeg
                mov     ds,ax


                lss     sp,DWORD PTR SPVar        ;又回到实方式
                sti
                mov     ax,4c00h


                int     21h


;----------------------------------------------------------------------------
;初始化全局描述表的子程序
;(1)把定义时预置的段值转移成32位段基地址并置入描述符内相应字段;初始化GDT中的描述符
;(2)初始化为GDTR准备的伪描述符                                  ;初始化GDT伪描述符
INIT_GDT        PROC    NEAR               
PUSH    DS
        MOV     AX,GDTSEG
        MOV     DS,AX
        MOV     CX,GDNUM                ;GDNUM是初始化的描述符个数
        MOV     SI,OFFSET EFFGDT        ;EFFGDT是开始偏移值
        ASSUME SI:PTR DESCRIPTOR
INITG:  MOV     AX,[SI].BASEL           ;取出预置的段值
        MOVZX   EAX,AX                  ;扩展到32位
        SHL     EAX,4
        SHLD    EDX,EAX,16              ;分解到2个16位寄存器
        MOV     [SI].BASEL,AX
        MOV     [SI].BASEM,DL           ;置入描述符相应字段
        MOV     [SI].BASEH,DH
        ADD     SI,SIZE DESCRIPTOR      ;调整到下一描述符
        LOOP    INITG
        ASSUME SI:NOTHING
        POP     DS
        ;
        MOV     BX,16                   ;初始化为GDTR准备的伪描述符
        MOV     AX,GDTSEG
        MUL     BX
        MOV     WORD PTR VGDTR.BASE,AX
        MOV     WORD PTR VGDTR.BASE+2,DX
        ret
INIT_GDT endp
;
;初始化演示任务局部描述符的子程序
;把定义时预置的段值转换成32位段基地址并置入描述符内相应字段
;入口参数:FS:SI=第一个要初始化的描述符
;         CX  = 要初始化的描述符个数
INIT_LDT        PROC
        ASSUME SI:PTR DESCRIPTOR


ILDT:   MOV     AX,FS:[SI].BASEL
        MOVZX   EAX,AX
        SHL     EAX,4
        SHLD    EDX,EAX,16
        MOV     FS:[SI].BASEL,AX
        MOV     FS:[SI].BASEM,DL
        MOV     FS:[SI].BASEH,DH
        ADD     SI,SIZE DESCRIPTOR
        LOOP    ILDT
        ASSUME SI:NOTHING
        ret
INIT_LDT endp
RCODESEG        ENDS
END Start


运行结果:见图





386SCD.INC

;..........................
.386P
;存储段和系统段描述符
DESCRIPTOR STRUC
LIMITL     DW 0
BASEL      DW 0
BASEM      DB 0
ATTRIBUTES DW 0
BASEH      DB 0


DESCRIPTOR ENDS
;.........................
;门描述符
GATE STRUC
OFFSETL  DW 0
SELECTOR DW 0
DCOUNT   DB 0
GTYPE    DB 0
OFFSETH  DW 0
GATE ENDS




;.........................
;伪描述符
PDESC STRUC
LIMIT DW 0
BASE  DD 0
PDESC ENDS
;.........................


;TASKSS任务状态段内容
TASKSS STRUC
TRLINK DW ?,0
TRESP0 DD ?
TRSS0   DW ?,0
TRESP1 DD ?
TRSS1   DW ?,0
TRESP2 DD ?
TRSS2   DW ?,0
TRCR3   DD ?
TREIP   DD ?
TREFLAG DW ?,?
TREAX   DD ?
TRECX   DD ?
TREDX   DD ?
TREBX   DD ?
TRESP   DD ?
TREBP   DD ?
TRESI   DD ?
TREDI   DD ?
TRES    DW ?,0
TRCS    DW ?,0
TRSS DW ?,0
TRDS DW ?,0
TRFS DW ?,0
TRGS DW ?,0
TRLDT DW ?,0
TRFLAG DW 0
TRIOMAP DW $+2
TASKSS ENDS
;..........................
;存储段描述符类型值说明
ATDR =90H
ATDW =92H
ATDWA =93H
ATCE =98H
ATCER =9AH
ATCCO =9CH
ATCCOR =9EH
;系统段描述符和门描述符类型值说明
ATLDT =82H
ATTASKGAT =85H
AT386TSS =89H
AT386CGAT =8CH
AT386IGAT =8EH
AT386TGAT =8FH
;DPL和RPL值说明
;..........................


DPL1 =20H
DPL2 =40H
DPL3 =60H
RPL1 =01H
RPL2 =02H
RPL3 =03H
IOPL1 =1000H
IOPL2 =2000H
IOPL3 =3000H
;.............................






;其它常量说明
D32 =4000H
TIL =04H
VMFL =0002H
IFL =0200H
;.............................


;段间转移及段间调用宏
JUMP32 MACRO selector,offsetv
DB 0EAH
DW offsetv
DW 0
DW selector
ENDM
CALL32 MACRO selector,offsetv
DB 09AH
DW offsetv
DW 0
DW selector
ENDM


JUMP16 MACRO selector,offsetv
DB 0EAH
DW offsetv
DW selector
ENDM
CALL16 MACRO selector,offsetv
DB 9AH
DW offsetv
DW selector
ENDM


;................................

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
程序名称:RadASM 版 本:2.2.1.9 汉 化 人:cao_cong 联系方式:cao_cong_hx@yahoo.com.cn 使用说明: 此汉化增强版根据RadASM作者网站正式发布的 2.2.1.9 版汉化,可对文完美支持,可编译DOS下的程序并可看到运行结果。这个版本增强了对 C 编译器的支持,增加了从已有具体的更新内容请大家参考安装目录下的 WhatsNew.txt。增强版附带的 MASM32 更新为 10.0,我在其放了开发驱动的相关文件,安装后即可使用,可以直接开发驱动程序。我还写了一篇《如何配置RasASM来支持你的编译器》的文章放在安装包,希望能给大家在为 RadASM 配置新的编译器时提供一点参考。汉化增强版适合于未安装Masm32及Viusual C++的用户,添加了RadASM的帮助文件及Win32 Api等帮助文件。RadASM可通过添加ini文件来支持别的语言,可以自己配置ini文件来支持你所使用的编程语言。此汉化增强版根据网友aboil的建议,添加了我最新修正的 OllyDBG 汉化第二版,选择安装后路径会自动设置好,直接可在RadASM调试你编译后的程序。 注意: 1、如果你曾安装了以前版本的RadASM汉化增强版,请不要卸载,只需覆盖安装即可。安装版本除了你选择了注册文件类型会在你的注册表添加数据(可到ICON目录下查看具体添加内容,如果选择卸载同样会删除这些数据)外,不会产生别的垃圾文件,所以没必要卸载。因为卸载时可能把你安装后新建的一些工程一并删除,请谨慎使用卸载(默认在Masm和Cpp新添加的工程不会被删除,但还是小心一点比较好)。若必须要卸载的话,请把你安装后新建的工程及配置文件备份到其它目录,再执行卸载! 2、这个版本我去掉了 TASM 5.0 的安装文件(主要为减小安装包体积),若要编译Tasm的程序的话请大家自己去下载TASM。 3、考虑到在有的未装VC的机器上测试时,编译时会提示找不到MSPDB60.DLL的错误,我在这个安装版本复制了一个VC的MSPDB60.DLL到你的系统目录,因为有些程序可能会用到它,所以在卸载时未作处理。你要是不需要的话,可到你的系统目录手工删除(建议保留这个文件)。 4、如果你第一次编译 MASM 的 Dos App,可能会在构建的时候提示找不到 *.obj 文件,其实这时 *.obj 文件已经生成了。简单的方法就是重新启动一下 RadASM,再编译、构建时就正常了。 增强版主要更新: 1、包含了编译 Win32 Asm 、C++ 的必须文件及我汉化的 OllyDBG(安装时需选择OllyDBG、Masm32及VC6.0这几个组件)。 2、添加了用于RadASM关联汇编文件的图标(安装时需选择文件关联组件),安装后你可在安装目录下的Icon目录内使用你喜欢的图标来定制关联文件的显示图标(替换图标时请把你需要替换的图标更名为原目录下的对应图标名称)。 3、添加了由怜香整理的8086汇编教程、Venjiang整理的 Win32 汇编教程、陈国强整理的Win32 API参考(VB描述)、www.vcok.com整理的C语言教程及经典的 Windows 程序设计电子书。 4、添加了一个Cpp的对话框程序模板文件。 5、添加了一个Masm的注册机程序示例,位于Masm的工程目录下的ASMkeyg文件夹内,推荐大家看一下。 060621新增: 1、把RadASM作者另一个资源编辑工具ResEd的汉化版也打包放在安装目录下,虽然RadASM自带有可视化的资源编辑器,但这个ResEd工具有些时候还是很有用的,你可以可视化的编辑其他的资源脚本,很方便。这个工具我以RadASM网站上的最新版本为基础汉化的。 2、从WinASM提取了两个模板(MDI和SDI模板),放了一个简单的注册机模板。 3、放了一个可以在对话框程序添加调整对话框控件大小代码的插件 KSresizer,已汉化并配置好了。把作者提供的例子程序也放在了MASM的工程目录下,有兴趣的可以看看。 4、把帮助文件更新为 RadASM 官方主页上的最新版本。 061207新增: 1、添加由 drizz 写的两个库文件: (1)、Stdlib.lib:包含一些对文件、注册表、INI文件、字串等一些常用的操作函数,可以直接调用,以减少编程工作量。 (2)、cryptohash.lib:密码学算法库,包含大部分常用密码学算法。 这两个库我都在RadASM添加了相应的API文件,方便写代码时自动列出函数。 081218: ResEd 更新为 2.2.0.0d 汉化版,支持把 .rc 文件的对话框部分导出为 RadASM 的 dlg 格式文件及添加 XP 界面等。 Language目录下的RadCHS.lng和RadENG.lng分别是简体文和英文语言文件,可在RadASM的选项->语言菜单选择。RadLNG.exe是用来查看语言文件的工具。 091209: 1、主程序汉化版本更新为 2.2.1.8f,同时更新语言文件。 2、ResEd 汉化版本更新为 2.2.0.5b。 3、除汉化了更新的插件外,重新汉化了 AdvEdit.dll(高级编辑) 插件。 091228: 1、主程序汉化版本更新为 2.2.1.9。 2、RadASM.ini 的 [Accept] 段下添加了 DontAsk=1,这样执行编译好的程序时不会再有提示(类似与 2.2.1.5 及以前版本)。如仍需要执行程序时提示的话,请把添加的 DontAsk=1 这一行删除。 一点建议: 1、建议把RadASM安装在根目录下,如 D:\RadASM。 2、如果在编译 Win32 Asm 程序时有问题,一个简单的方法就是把 RadASM 目录下的 Masm32 剪切到 RadASM 安装的根目录,如 D:\Masm32,再在 RadASM 重新设置路径。 3、RadASM 添加的插件 CodeTemplates.dll 是用于在编辑代码时输入定义好的代码模板的,默认调出方式是Ctrl+J,可根据Addins\Help目录下的帮助文件CodeTemplates.Txt(我已翻译过)来自己配置需要的模板。 4、格式化代码的插件(TabAddin.dll)我根据其帮助文档和自己的测试结果进行了汉化。本来想把这个插件的帮助文档一起汉化的,可实在没太多时间,只能让大家根据汉化插件的界面来对照英文的帮助文档来理解此插件的功能,造成不便的地方还望大家原谅!简单说一下此插件汉化后菜单上各个按钮的功能:“左移”:把选代码左移一个制表符;“右移”:选代码右移一个制表符;“规范化”:把选的排列不整齐的代码按照选项的设置进行排列;“标准化”:把你选代码按选项的设置进行整理,使代码具有更好的可读性;“显示选项”:显示设置选项。 声明: 1、此汉化软件是免费软件,请在转载时保留其内容的完整性! 2、此软件仅用于个人学习使用,禁止用于商业用途,否则后果自负! HA.RadASM.v2.2.1.9.cao_cong.exe 的 MD5 值: 7BE397D8B107D68286EA07964DEF8A61
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值