55、深入探索MS-DOS文件输入输出服务

深入探索MS-DOS文件输入输出服务

1. 标准MS-DOS文件输入输出服务基础

在MS-DOS环境下,文件的输入输出操作是非常重要的。下面我们先来看两个基础的程序: ReadString WriteString

ReadString 程序用于从键盘读取字符串,直到用户按下回车键为止,它返回输入字符串的大小。以下是其代码实现:

; Returns:  AX = size of the input string
; Comments: Stops when the Enter key (0Dh) is pressed.
;--------------------------------------------------------
push  cx
; save registers
push  si
push  cx
; save digit count again
mov   si,dx
; point to input buffer
L1:
mov   ah,1
; function: keyboard input
int   21h
; returns character in AL
cmp   al,0Dh
; end of line?
je    L2
; yes: exit
mov   [si],al
; no: store the character
inc   si
; increment buffer pointer
loop  L1
; loop until CX=0
L2:
mov  byte ptr [si],0
; end with a null byte
pop  ax
; original digit count
sub  ax,cx
; AX = size of input string
pop  si
; restore registers
pop  cx
ret
ReadString ENDP

这个程序的执行流程如下:
1. 保存相关寄存器的值。
2. 不断从键盘读取字符,直到用户按下回车键。
3. 将读取的字符存储到缓冲区中。
4. 最后以空字节结束字符串,并返回字符串的大小。

WriteString 程序则用于将以空字符结尾的字符串写入标准输出。它调用了一个名为 Str_length 的辅助程序来获取字符串的字节数。代码如下:

;--------------------------------------------------------
WriteString PROC
; Writes a null-terminated string to standard output
; Receives: DS:DX = address of string
; Returns: nothing
;--------------------------------------------------------
pusha
push  ds           
; set ES to DS
pop   es
mov   di,dx        
; ES:DI = string ptr
call  Str_length   
; AX = string length
mov   cx,ax        
; CX = number of bytes
mov   ah,40h       
; write to file or device
mov   bx,1         
; standard output handle
int   21h          
; call MS-DOS
popa
ret
WriteString ENDP

其执行步骤为:
1. 保存所有通用寄存器的值。
2. 获取字符串的长度。
3. 使用 INT 21h 的功能 40h 将字符串写入标准输出。
4. 恢复寄存器的值并返回。

2. 读取和复制文本文件示例

接下来,我们看一个读取和复制文本文件的示例程序 Readfile.asm 。它展示了几个重要的 INT 21h 功能:
- 功能 716Ch:创建新文件或打开现有文件。
- 功能 3Fh:从文件或设备读取数据。
- 功能 40h:向文件或设备写入数据。
- 功能 3Eh:关闭文件句柄。

以下是完整的 Readfile.asm 代码:

; Read a text file         (Readfile.asm)
; Read, display, and copy a text file.
INCLUDE Irvine16.inc
.data
BufSize = 5000
infile    BYTE "my_text_file.txt",0
outfile   BYTE "my_output_file.txt",0
inHandle  WORD ?
outHandle WORD ?
buffer    BYTE BufSize DUP(?)
bytesRead WORD ?
.code
main PROC
mov
ax,@data
mov
ds,ax
; Open the input file
mov
ax,716Ch   
; extended create or open
mov
bx,0      
; mode = read-only
mov
cx,0
; normal attribute
mov
dx,1
; action: open
mov
si,OFFSET infile
int
21h       
; call MS-DOS
jc
quit
; quit if error
mov
inHandle,ax
; Read the input file
mov
ah,3Fh
; read file or device
mov
bx,inHandle
; file handle
mov
cx,BufSize
; max bytes to read
mov
dx,OFFSET buffer
; buffer pointer
int
21h
jc
quit
; quit if error
mov
bytesRead,ax
; Display the buffer
mov
ah,40h
; write file or device
mov
bx,1
; console output handle
mov
cx,bytesRead
; number of bytes
mov
dx,OFFSET buffer
; buffer pointer
int
21h
jc
quit
; quit if error
; Close the file
mov
ah,3Eh    
; function: close file
mov
bx,inHandle
; input file handle
int
21h       
; call MS-DOS
jc
quit
; quit if error
; Create the output file
mov
ax,716Ch   
; extended create or open
mov
bx,1      
; mode = write-only
mov
cx,0
; normal attribute
mov
dx,12h
; action: create/truncate
mov
si,OFFSET outfile
int
21h       
; call MS-DOS
jc
quit
; quit if error
mov
outHandle,ax
; save handle
; Write buffer to new file
mov
ah,40h
; write file or device
mov
bx,outHandle
; output file handle
mov
cx,bytesRead
; number of bytes
mov
dx,OFFSET buffer
; buffer pointer
int
21h
jc
quit
; quit if error
; Close the file
mov
ah,3Eh    
; function: close file
mov
bx,outHandle
; output file handle
int
21h       
; call MS-DOS
quit:
call
Crlf
exit
main ENDP
END main

这个程序的执行流程可以用以下 mermaid 流程图表示:

graph TD;
    A[开始] --> B[打开输入文件];
    B --> C{是否出错};
    C -- 是 --> G[退出];
    C -- 否 --> D[读取输入文件];
    D --> E{是否出错};
    E -- 是 --> G[退出];
    E -- 否 --> F[显示缓冲区内容];
    F --> H{是否出错};
    H -- 是 --> G[退出];
    H -- 否 --> I[关闭输入文件];
    I --> J{是否出错};
    J -- 是 --> G[退出];
    J -- 否 --> K[创建输出文件];
    K --> L{是否出错};
    L -- 是 --> G[退出];
    L -- 否 --> M[将缓冲区内容写入输出文件];
    M --> N{是否出错};
    N -- 是 --> G[退出];
    N -- 否 --> O[关闭输出文件];
    O --> G[退出];
3. 读取MS-DOS命令行尾信息

在MS-DOS中,当程序启动时,命令行上的额外文本会自动存储在位于内存偏移量 80h 处的 128 字节的 MS-DOS 命令行尾区域。这个区域位于由 ES 寄存器指定的段地址开始的位置,被称为程序段前缀(PSP)。

GetCommandTail 程序可以从 Irvine16 库中获取正在运行的程序的命令行尾的副本。以下是其代码:

;--------------------------------------------------
GetCommandTail PROC
;
; Gets a copy of the MS-DOS command tail at PSP:80h.
; Receives: DX contains the offset of the buffer
;    that receives a copy of the command tail.
; Returns: CF=1 if the buffer is empty; otherwise,
;    CF=0.
;--------------------------------------------------
SPACE = 20h
push es
pusha
; save general registers
mov
ah,62h
; get PSP segment address
int
21h
; returned in BX
mov
es,bx
; copied to ES
mov
si,dx
; point to buffer
mov
di,81h
; PSP offset of command tail
mov
cx,0
; byte count
mov
cl,es:[di-1]
; get length byte
cmp
cx,0
; is the tail empty?
je
L2
; yes: exit
cld
; scan in forward direction
mov
al,SPACE
; space character
repz
scasb
; scan for non space
jz
L2
; all spaces found
dec
di
; non space found
inc
cx
L1:
mov
al,es:[di]
; copy tail to buffer
mov
[si],al
; pointed to by DS:SI
inc
si
inc
di
loop
L1
clc
; CF=0 means tail found
jmp
L3
L2:
stc
; CF=1 means no command tail
L3:
mov
byte ptr [si],0
; store null byte
popa
; restore registers
pop
es
ret
GetCommandTail ENDP

这个程序的主要步骤如下:
1. 保存当前的 ES 寄存器值。
2. 使用 INT 21h 功能 62h 获取 PSP 段地址,并将其复制到 ES 寄存器。
3. 定位命令行尾的长度字节。
4. 跳过前导空格。
5. 将命令行尾的内容复制到指定的缓冲区。
6. 根据缓冲区是否为空设置进位标志。

4. 创建二进制文件示例

二进制文件是指文件中存储的数据是程序数据的二进制映像。例如,如果程序创建并填充了一个双字数组,将这个数组写入文本文件需要将每个整数转换为字符串并分别写入,而更高效的方法是直接将数组的二进制映像写入文件。

Binfile.asm 程序演示了如何创建一个包含双字数组的二进制文件,然后读取该文件并显示其中的值。以下是代码:

; Binary File Program         (Binfile.asm)
; This program creates a binary file containing 
; an array of doublewords. It then reads the file
; back in and displays the values.
INCLUDE Irvine16.inc
.data
myArray DWORD 50 DUP(?)
fileName   BYTE "binary array file.bin",0
fileHandle WORD ?
commaStr   BYTE ", ",0
; Set CreateFile to zero if you just want to
; read and display the existing binary file.
CreateFile = 1
.code
main PROC
mov
ax,@data
mov
ds,ax
.IF CreateFile EQ 1
call
FillTheArray
call
DisplayTheArray
call
CreateTheFile
call
WaitMsg
call
Crlf
.ENDIF
call
ReadTheFile
call
DisplayTheArray
quit:
call
Crlf
exit
main ENDP
;------------------------------------------------------
ReadTheFile PROC
;
; Open and read the binary file.
; Receives: nothing.
; Returns: nothing
;------------------------------------------------------
mov
ax,716Ch    
; extended file open
mov
bx,0
; mode: read-only
mov
cx,0      
; attribute: normal
mov
dx,1
; open existing file
mov
si,OFFSET fileName
; filename
int
21h       
; call MS-DOS
jc
quit
; quit if error
mov
fileHandle,ax
; save handle
; Read the input file, then close the file.
mov
ah,3Fh
; read file or device
mov
bx,fileHandle
; file handle
mov
cx,SIZEOF myArray
; max bytes to read
mov
dx,OFFSET myArray
; buffer pointer
int
21h
jc
quit
; quit if error
mov
ah,3Eh    
; function: close file
mov
bx,fileHandle
; output file handle
int
21h       
; call MS-DOS
quit:
ret
ReadTheFile ENDP
;------------------------------------------------------
DisplayTheArray PROC
;
; Display the doubleword array.
; Receives: nothing.
; Returns: nothing
;------------------------------------------------------
mov
CX,LENGTHOF myArray
mov
si,0
L1:
mov
eax,myArray[si]
; get a number
call
WriteHex
; display the number
mov
edx,OFFSET commaStr
; display a comma
call
WriteString
add
si,TYPE myArray
; next array position
loop
L1
ret
DisplayTheArray ENDP
;------------------------------------------------------
FillTheArray PROC
;
; Fill the array with random integers.
; Receives: nothing.
; Returns: nothing
;------------------------------------------------------
mov
CX,LENGTHOF myArray
mov
si,0
L1:
mov
eax,1000
; generate random integers
call
RandomRange
; between 0 - 999 in EAX
mov
myArray[si],eax
; store in the array
add
si,TYPE myArray
; next array position
loop
L1
ret
FillTheArray ENDP
;------------------------------------------------------
CreateTheFile PROC
;
; Create a file containing binary data.
; Receives: nothing.
; Returns: nothing
;------------------------------------------------------
mov
ax,716Ch    
; create file
mov
bx,1
; mode: write only
mov
cx,0      
; normal file
mov
dx,12h
; action: create/truncate
mov
si,OFFSET fileName
; filename
int
21h       
; call MS-DOS
jc
quit
; quit if error
mov
fileHandle,ax
; save handle
; Write the integer array to the file.
mov
ah,40h
; write file or device
mov
bx,fileHandle
; output file handle
mov
cx,SIZEOF myArray
; number of bytes
mov
dx,OFFSET myArray
; buffer pointer
int
21h
jc
quit
; quit if error
; Close the file.
mov
ah,3Eh
; function: close file
mov
bx,fileHandle
; output file handle
int
21h
; call MS-DOS
quit:
ret
CreateTheFile ENDP
END main

这个程序的执行流程可以用以下表格总结:
| 步骤 | 操作 | 功能 |
| ---- | ---- | ---- |
| 1 | FillTheArray | 用随机整数填充数组 |
| 2 | DisplayTheArray | 显示数组内容 |
| 3 | CreateTheFile | 创建包含二进制数据的文件 |
| 4 | ReadTheFile | 打开并读取二进制文件 |
| 5 | DisplayTheArray | 再次显示数组内容 |

通过以上内容,我们对MS-DOS环境下的文件输入输出操作有了更深入的了解,包括字符串的读取和写入、文件的读写和复制、命令行尾信息的获取以及二进制文件的创建和读取等。这些操作在MS-DOS编程中是非常基础且重要的。

5. 重要的MS-DOS函数总结

在MS-DOS编程中,有许多重要的 INT 21h 函数,下面为大家详细介绍:
| 函数编号 | 功能 | 描述 |
| ---- | ---- | ---- |
| 4Ch | 终止当前程序 | 结束程序并返回操作系统 |
| 2 和 6 | 写入单个字符到标准输出 | 将一个字符输出到标准输出设备 |
| 5 | 写入单个字符到打印机 | 把字符发送到打印机进行打印 |
| 9 | 写入字符串到标准输出 | 输出以空字符结尾的字符串到标准输出 |
| 40h | 写入字节数组到文件或设备 | 可将指定数量的字节写入文件或设备 |
| 1 | 从标准输入读取单个字符 | 从标准输入设备获取一个字符 |
| 6 | 从标准输入读取字符且不等待 | 不等待用户输入,直接尝试读取字符 |
| 0Ah | 从标准输入读取缓冲字符串 | 读取用户输入的字符串到缓冲区 |
| 0Bh | 获取标准输入缓冲区状态 | 检查标准输入缓冲区的状态 |
| 3Fh | 从文件或设备读取字节数组 | 从文件或设备中读取指定数量的字节 |
| 2Ah | 获取系统日期 | 返回当前系统的日期 |
| 2Bh | 设置系统日期 | 可以修改系统的日期 |
| 2Ch | 获取系统时间 | 得到当前系统的时间 |
| 2Dh | 设置系统时间 | 对系统时间进行设置 |
| 716Ch | 创建文件或打开现有文件 | 可创建新文件或打开已存在的文件 |
| 3Eh | 关闭文件句柄 | 关闭指定的文件句柄 |
| 42h | 移动文件位置指针 | 改变文件指针的位置 |
| 5706h | 获取文件创建日期和时间 | 得到文件的创建日期和时间 |
| 62h | 返回程序段前缀地址的段部分 | 获取程序段前缀的段地址 |

这些函数在不同的场景下发挥着重要作用,例如在文件操作、日期时间处理、输入输出等方面。

6. 编程练习

以下是一些编程练习,要求在实地址模式下完成,并且除特殊说明外,需使用 INT 21h 函数进行所有输入输出操作。

6.1 读取文本文件

编写一个程序,打开一个文件进行输入,读取文件内容并以十六进制形式显示在屏幕上。输入缓冲区设置为 256 字节左右,使用循环多次调用 INT 21h 功能 3Fh,直到整个文件处理完毕。

操作步骤如下:
1. 打开文件:使用 INT 21h 功能 716Ch 以只读模式打开文件。
2. 循环读取:在循环中,使用 INT 21h 功能 3Fh 每次读取 256 字节到缓冲区。
3. 显示内容:将缓冲区内容以十六进制形式输出到屏幕。
4. 检查文件结束:判断是否到达文件末尾,如果未结束则继续循环。
5. 关闭文件:使用 INT 21h 功能 3Eh 关闭文件。

graph TD;
    A[开始] --> B[打开文件];
    B --> C{是否出错};
    C -- 是 --> G[退出];
    C -- 否 --> D[读取数据到缓冲区];
    D --> E{是否到达文件末尾};
    E -- 是 --> F[关闭文件];
    E -- 否 --> H[以十六进制显示缓冲区内容];
    H --> D;
    F --> G;
6.2 复制文本文件

修改 Readfile 程序,使其能够读取任意大小的文件。假设缓冲区小于输入文件,使用循环读取所有数据,缓冲区大小设为 256 字节。如果 INT 21h 函数调用后进位标志被设置,显示相应的错误信息。

操作步骤:
1. 打开输入文件和输出文件:分别使用 INT 21h 功能 716Ch 以只读和只写模式打开。
2. 循环读取和写入:在循环中,使用 INT 21h 功能 3Fh 读取 256 字节到缓冲区,再使用 INT 21h 功能 40h 将缓冲区内容写入输出文件。
3. 检查错误:每次调用 INT 21h 函数后检查进位标志,若设置则显示错误信息并退出。
4. 关闭文件:使用 INT 21h 功能 3Eh 关闭输入和输出文件。

6.3 设置日期

编写一个程序,显示当前日期并提示用户输入新日期。如果用户输入非空日期,则用其更新系统日期。

操作步骤:
1. 获取当前日期:使用 INT 21h 功能 2Ah 获取当前系统日期。
2. 显示日期:将获取的日期显示给用户。
3. 提示输入:提示用户输入新日期。
4. 检查输入:判断用户输入是否为空,若不为空则使用 INT 21h 功能 2Bh 设置新日期。

6.4 大写转换

编写程序,使用 INT 21h 从键盘输入小写字母并将其转换为大写字母,只显示大写字母。

操作步骤:
1. 读取字符:使用 INT 21h 功能 1 从键盘读取字符。
2. 判断大小写:检查字符是否为小写字母。
3. 转换并显示:如果是小写字母,将其转换为大写字母并显示。

6.5 文件创建日期

编写一个过程,显示文件的创建日期和文件名。在 DX 寄存器中传递文件名指针,编写测试程序,用不同的文件名(包括长文件名)测试该过程。如果文件未找到,显示相应的错误信息。

操作步骤:
1. 获取文件信息:使用 INT 21h 功能 5706h 获取文件的创建日期和时间。
2. 显示信息:将文件名和创建日期显示在屏幕上。
3. 错误处理:如果文件未找到,显示错误信息。

6.6 文本匹配程序

编写一个程序,打开一个最多包含 60K 字节的文本文件,进行不区分大小写的字符串搜索。字符串和文件名由用户输入,显示文件中包含该字符串的每一行,并在每行前加上行号。

操作步骤:
1. 获取用户输入:获取用户输入的字符串和文件名。
2. 打开文件:使用 INT 21h 功能 716Ch 以只读模式打开文件。
3. 逐行读取:在循环中逐行读取文件内容。
4. 字符串匹配:使用字符串匹配算法检查每行是否包含目标字符串。
5. 显示结果:如果匹配成功,显示行号和该行内容。
6. 关闭文件:使用 INT 21h 功能 3Eh 关闭文件。

6.7 文件加密使用异或

增强文件加密程序,具体步骤如下:
1. 提示用户输入:要求用户输入明文文件和密文文件的名称。
2. 打开文件:使用 INT 21h 功能 716Ch 分别以只读和只写模式打开明文文件和密文文件。
3. 获取加密代码:让用户输入一个 1 到 255 之间的整数作为加密代码。
4. 读取和加密:使用 INT 21h 功能 3Fh 读取明文文件到缓冲区,对每个字节进行异或操作。
5. 写入密文文件:使用 INT 21h 功能 40h 将加密后的缓冲区内容写入密文文件。
6. 关闭文件:使用 INT 21h 功能 3Eh 关闭两个文件。

6.8 单词计数程序

编写一个程序,统计文本文件中的单词数量。提示用户输入文件名,然后在屏幕上显示单词计数结果。

操作步骤:
1. 获取文件名:提示用户输入要统计的文件名。
2. 打开文件:使用 INT 21h 功能 716Ch 以只读模式打开文件。
3. 读取文件:逐字节读取文件内容。
4. 单词计数:根据空格和标点符号判断单词的开始和结束,进行计数。
5. 显示结果:使用 WriteDec 过程显示单词数量。
6. 关闭文件:使用 INT 21h 功能 3Eh 关闭文件。

通过这些编程练习,可以进一步巩固对MS-DOS文件输入输出服务的理解和掌握,提高在MS-DOS环境下的编程能力。在实际编程过程中,要注意对错误的处理,确保程序的健壮性。同时,合理运用各种 INT 21h 函数,能够高效地完成各种任务。

基于数据驱动的 Koopman 算子的递归神经网络模型线性化,用于纳米定位系统的预测控制研究(Matlab代码实现)内容概要:本文围绕“基于数据驱动的 Koopman 算子的递归神经网络模型线性化,用于纳米定位系统的预测控制研究”展开,提出了一种结合数据驱动方法与Koopman算子理论的递归神经网络(RNN)模型线性化方法,旨在提升纳米定位系统的预测控制精度与动态响应能力。研究通过构建数据驱动的线性化模型,克服了传统非线性系统建模复杂、计算开销大的问题,并在Matlab平台上实现了完整的算法仿真与验证,展示了该方法在高精度定位控制中的有效性与实用性。; 适合人群:具备一定自动化、控制理论或机器学习背景的科研人员与工程技术人员,尤其是从事精密定位、智能控制、非线性系统建模与预测控制相关领域的研究生与研究人员。; 使用场景及目标:①应用于纳米级精密定位系统(如原子力显微镜、半导体制造设备)中的高性能预测控制;②为复杂非线性系统的数据驱动建模与线性化提供新思路;③结合深度学习与经典控制理论,推动智能控制算法的实际落地。; 阅读建议:建议读者结合Matlab代码实现部分,深入理解Koopman算子与RNN结合的建模范式,重点关注数据预处理、模型训练与控制系统集成等关键环节,并可通过替换实际系统数据进行迁移验证,以掌握该方法的核心思想与工程应用技巧。
基于粒子群算法优化Kmeans聚类的居民用电行为分析研究(Matlb代码实现)内容概要:本文围绕基于粒子群算法(PSO)优化Kmeans聚类的居民用电行为分析展开研究,提出了一种结合智能优化算法与传统聚类方法的技术路径。通过使用粒子群算法优化Kmeans聚类的初始聚类中心,有效克服了传统Kmeans算法易陷入局部最优、对初始值敏感的问题,提升了聚类的稳定性和准确性。研究利用Matlab实现了该算法,并应用于居民用电数据的行为模式识别与分类,有助于精细化电力需求管理、用户画像构建及个性化用电服务设计。文档还提及相关应用场景如负荷预测、电力系统优化等,并提供了配套代码资源。; 适合人群:具备一定Matlab编程基础,从事电力系统、智能优化算法、数据分析等相关领域的研究人员或工程技术人员,尤其适合研究生及科研人员。; 使用场景及目标:①用于居民用电行为的高效聚类分析,挖掘典型用电模式;②提升Kmeans聚类算法的性能,避免局部最优问题;③为电力公司开展需求响应、负荷预测和用户分群管理提供技术支持;④作为智能优化算法与机器学习结合应用的教学与科研案例。; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,深入理解PSO优化Kmeans的核心机制,关注参数设置对聚类效果的影响,并尝试将其应用于其他相似的数据聚类问题中,以加深理解和拓展应用能力。
在大数据技术快速发展的背景下,网络爬虫已成为信息收集与数据分析的关键工具。Python凭借其语法简洁和功能丰富的优势,被广泛用于开发各类数据采集程序。本项研究“基于Python的企查查企业信息全面采集系统”即在此趋势下设计,旨在通过编写自动化脚本,实现对企查查平台所公示的企业信用数据的系统化抓取。 该系统的核心任务是构建一个高效、可靠且易于扩展的网络爬虫,能够模拟用户登录企查查网站,并依据预设规则定向获取企业信息。为实现此目标,需重点解决以下技术环节:首先,必须深入解析目标网站的数据组织与呈现方式,包括其URL生成规则、页面HTML架构以及可能采用的JavaScript动态渲染技术。准确掌握这些结构特征是制定有效采集策略、保障数据完整与准确的前提。 其次,针对网站可能设置的反爬虫机制,需部署相应的应对方案。例如,通过配置模拟真实浏览器的请求头部信息、采用多代理IP轮换策略、合理设置访问时间间隔等方式降低被拦截风险。同时,可能需要借助动态解析技术处理由JavaScript加载的数据内容。 在程序开发层面,将充分利用Python生态中的多种工具库:如使用requests库发送网络请求,借助BeautifulSoup或lxml解析网页文档,通过selenium模拟浏览器交互行为,并可基于Scrapy框架构建更复杂的爬虫系统。此外,json库用于处理JSON格式数据,pandas库则协助后续的数据整理与分析工作。 考虑到采集的数据规模可能较大,需设计合适的数据存储方案,例如选用MySQL或MongoDB等数据库进行持久化保存。同时,必须对数据进行清洗、去重与结构化处理,以确保其质量满足后续应用需求。 本系统还需包含运行监控与维护机制。爬虫执行过程中可能遭遇网站结构变更、数据格式调整等意外情况,需建立及时检测与自适应调整的能力。通过定期分析运行日志,评估程序的效率与稳定性,并持续优化其性能表现。 综上所述,本项目不仅涉及核心爬虫代码的编写,还需在反爬应对、数据存储及系统维护等方面进行周密设计。通过完整采集企查查的企业数据,该系统可为市场调研、信用评价等应用领域提供大量高价值的信息支持。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值