资讯动态

DOS实模式汇编密码系统:纯软中断实现的x86人机交互

发布时间:2026/10/28 3:49:13 来源:尧图企业网站定制
简介本资源是面向高校电子信息类专业本科生的《微机原理及应用技术》课程设计实践材料聚焦密码校验这一典型软硬协同任务帮助学生掌握汇编级安全验证逻辑与MASM开发全流程。压缩包为1个249KB的Word文档.doc完整包含河北科技大学电信091班课程设计报告全文涵盖题目说明、详细设计要求如8–16位混合字符校验、明文禁用与哈希思路、进度与小组分工安排、MASM环境配置方法、核心算法实现步骤、带注释的完整汇编代码、程序界面截图及流程图、测试用例分析与课设总结反思等11个结构化章节。文档内容详实、排版规范代码模块按“密码接收→长度判断→字符类型扫描→错误提示→退出”分节注释便于理解底层指令如LEA、CMP、JNE、CALL的实际作用。目前已有652人学习下载是微机原理课设中兼具教学性、可复现性与工程参考价值的高质量结题范本。1. 这不是“密码强度检测”而是一段能跑在 DOS 里的真实汇编黑匣子主菜单→输入密码→三次错误即退→全用 INT 21H 和 INT 10H 控制光标与字符串连回车换行都要手动发 0DH/0AH连矩形边框都靠 ASCII 码 186/187/200/201 拼出来——它就是《微机原理课设》里最硬核的落地实践一个没有操作系统 API、不依赖 C 运行时、纯靠软中断和寄存器调度的密码校验系统。它不处理哈希、不连数据库、不加盐但它真实复现了 x86 实模式下“人机交互”的原始手感你敲下的每个字符都经由 INT 16H 读入 AL你看到的每行提示都靠 INT 21H 功能号 09H 从 DS:DX 输出你输错三次后程序干净退出到 DOS靠的是 INT 21H 功能号 4CH。适合刚学完 8086 寄存器、还没碰过保护模式、想亲手把“MOV AX,3; INT 10H”变成可执行界面的电子信息类本科生——这不是玩具 Demo是当年在 MASM 5.0 DOSBox 里真能双击运行、按 1/2/3 切换功能、输错三次自动关掉的完整课设工程。2. 项目结构与技术栈实模式汇编的最小可行闭环2.1 它到底有几个文件结构长什么样这个项目本质是单文件汇编工程所有逻辑主菜单、输入、校验、退出全部写在一个.asm文件里无头文件、无链接库、无外部依赖。整个代码段CODE SEGMENT自包含数据段DATA SEGMENT紧随其后最后以END START收尾。这种结构是实模式汇编的典型范式代码即入口段地址由 DOS 加载器自动设置ASSUME CS:CODE, DS:CODE告诉汇编器“代码段和数据段用同一个段基址”省去显式初始化 DS 的步骤——这是 MASM 5.0 在 DOS 下能跑通的关键前提。提示你不会看到#include stdio.h或import sys也不会有makefile或CMakeLists.txt。它的构建流程极简ml /c password.asm→ 生成password.objlink password.obj→ 生成password.exe双击运行或在 DOSBox 中键入password回车。2.2 技术栈就三样MASM 5.0 DOS 6.22 x86 实模式指令集MASM 5.0不是最新版但它是课程设计事实标准。它对INT 21H、INT 10H的宏支持成熟语法宽松允许DB STRING直接定义字符串且.obj格式与 DOS 的link.exe兼容性最好。新版 MASM如 10.0默认生成 Win32 PE 格式反而跑不起来。DOS 6.22 环境所有软中断调用INT 16H,INT 21H,INT 10H均基于 DOS BIOS 接口。INT 21H功能号 09H显示字符串、0AH输入字符串、4CH退出程序是核心命脉INT 10H功能号 00H设文本模式、0EH光标移动负责界面控制INT 16H功能号 00H读键盘捕获用户按键。x86 实模式指令全程使用 16 位寄存器AX, BX, CX, DX, SI, DI, BP, SP地址计算靠段:偏移如DS:DX字符串操作依赖REPZ CMPSB带重复前缀的字节比较内存布局靠DB/DUP显式声明缓冲区MSG1 DB 255,0是 DOS 输入缓冲区标准格式首字节为最大长度次字节为实际输入长度后续为字符。2.3 目录结构即代码段落从 START 到 END 的五层逻辑流整个.asm文件可划分为五个物理区块对应程序生命周期区块位置关键标签/指令功能定位技术要点1. 初始化区START:开头MOV AX,CODE; MOV DS,AX; CLD设置代码/数据段一致清方向标志CLD保证SI/DI自增CLD是REPZ CMPSB正常工作的前提漏写会导致字符串比较永远失败2. 主循环区AGAIN:标签起含MENU显示、INT 16H读键、CMP AL,1分支实现“按 1→输入、按 2→校验、按 3→退出”的状态机所有分支最终JMP AGAIN形成死循环EXIT是唯一跳出点3. 输入子程序LP1:标签含LEA DX,TIPS; INT 21HLEA DX,MSG1; INT 21H处理“输入密码”功能将用户输入存入BUF1MSG1 DB 255,0后紧跟BUF1 DB 255 DUP(0)DOS 自动将输入字符填入BUF1长度写入MSG114. 校验子程序LP2:标签含CMP CL,MSG21比长度REPZ CMPSB比内容核心安全逻辑先比长度再逐字节比内容错误三次跳WRONGREPZ CMPSB会修改CX和ZF必须在比较前MOV CX,xxx且CLD已置位5. 数据定义区MENU DB ...,PASS DB ...,MSG1 DB 255,0,BUF1 DB 255 DUP(0)定义所有字符串、缓冲区、界面字符186/187/200/201矩形框用 ASCII 扩展码186│, 187┐, 200└, 201┌, 205─纯字符拼接无图形库2.4 为什么不用高级语言——实模式下“控制权”的代价与回报有人问Python 三行搞定密码校验为何要写 150 行汇编答案藏在INT 21H的调用开销里。在 DOS 下每次INT 21H都触发一次中断向量查表IVT[0x21]、压栈、跳转、执行 BIOS 服务、恢复现场——这看似低效却是直接操控硬件资源的唯一通道。比如INT 10H功能号 00H 设置AL03h直接让 CRT 控制器切换到 80×25 彩色文本模式无需驱动INT 16H读键AL 返回 ASCII 码AH 返回扫描码你能精确知道用户按的是“数字1”还是“小键盘1”INT 21H功能号 0AH 输入DOS 自动处理回车、退格、缓冲区溢出保护比自己写键盘扫描循环可靠十倍。这不是炫技是微机原理课的核心目标理解软件如何通过 CPU 指令与硬件固件对话。当你亲手写出MOV AH,0AH; INT 21H并看到光标闪烁等待输入时你触摸到了计算机最底层的呼吸节奏。3. 核心模块拆解从主菜单到密码校验的完整链路3.1 主菜单实现用 ASCII 码手绘矩形界面主菜单MENU不是调用 GUI 库画出来的而是用DB指令逐字节定义的字符串数组。关键代码如下MENU DB 5 DUP(0AH) ; 5个换行清屏效果 DB 31 DUP( ),MAIN MENU,0DH,0AH ; 31空格MAIN MENU回车换行 DB 25 DUP( ),201,21 DUP(205),187,0DH,0AH ; 25空格┌21个─┐回车换行 DB 25 DUP( ),186, 1.INPUT THE PASSWORD,186,0DH,0AH ; 25空格│1.INPUT...│回车换行 DB 25 DUP( ),186, 2. CHECK THE PASSWORD , 186,0DH,0AH ; 同上选项2 DB 25 DUP( ),186, 3.RETURN TO DOS ... ,186,0DH,0AH ; 同上选项3 DB 25 DUP( ),200,21 DUP(205),188,0DH,0AH ; 25空格└21个─┘回车换行 DB 28 DUP( ),CHOICE(1,2,3):$ ; 28空格CHOICE(1,2,3):$结尾表示字符串结束这段代码的精妙在于201/187/200/188/186/205是 IBM PC 字符集扩展码对应边框字符┌, ┐, └, ┘, │, ─DOS 文本模式直接支持渲染DUP()是 MASM 宏25 DUP( )生成 25 个空格用于水平居中$结尾是 DOS 字符串惯例INT 21H功能号 09H 要求字符串以$结束否则会越界打印乱码0DH,0AH是回车Carriage Return和换行Line Feed的 ASCII 码缺一不可——只写0AH在 DOS 下可能只换行不归位导致文字错位。注意MENU定义在代码段末尾但LEA DX,MENU指令能正确加载其偏移地址因为ASSUME DS:CODE让数据段寄存器 DS 指向代码段基址DX存储的是MENU在该段内的偏移量。3.2 输入密码子程序 LP1DOS 输入缓冲区的正确用法LP1是“输入密码”功能的实现它展示了 DOS 输入服务INT 21H功能号 0AH的标准用法LP1: ; 过程一输入密码 MOV AX,3 ; 设置文本显示模式80x25彩色 INT 10H LEA DX,TIPS ; 加载提示字符串地址INPUT A STRING: $ MOV AH,9 ; DOS显示字符串功能 INT 21H LEA DX,MSG1 ; 加载输入缓冲区地址 MOV AH,0AH ; DOS输入字符串功能需缓冲区格式max_len, actual_len, [chars...] INT 21H MOV AX,0E0DH ; 光标移动0Eh功能号写字符并移动光标0DH回车ASCII INT 10H MOV AL,0AH ; 再发换行ASCII INT 10H RET关键参数说明MSG1 DB 255,0这是 DOS 输入缓冲区的强制格式。首字节255表示最多接收 255 个字符含回车第二字节0初始值为 0DOS 在输入完成后会将实际输入字符数不含回车写入此处BUF1 DB 255 DUP(0)紧跟MSG1定义DOS 将用户输入的字符不含回车依次存入BUF1因此BUF1是真正的密码存储区MOV AX,0E0DH; INT 10H0Eh是INT 10H的“写字符并移动光标”功能0DH是回车 ASCII此指令让光标回到行首MOV AL,0AH; INT 10H0AH是换行 ASCII此指令让光标下移一行组合实现“回车换行”效果。提示若省略最后两行光标控制输入密码后光标会停留在提示符末尾影响后续菜单显示。这是新手最容易忽略的“界面体验细节”。3.3 密码校验子程序 LP2三次错误机制与字节级比较LP2是整个项目的技术核心它实现了“输错三次退出”的业务规则和“密码完全匹配”的安全逻辑LP2: ; 过程二密码校验 MOV AX,3 ; 重置文本模式 INT 10H CLC ; 清进位标志为后续STC/JC做准备 PUSH DS ; 保存DS POP ES ; ESDS为CMPSB准备CMPSB用ES:DI和DS:SI MOV BP,3 ; BP3计数器最多允许3次错误 SSS: ; 错误重试标签 LEA DX,PASS ; 显示ENTER YOUR PASSWORD: $ MOV AH,9 INT 21H LEA DX,MSG2 ; 加载校验输入缓冲区 MOV AH,0AH ; DOS输入 INT 21H LEA SI,BUF1 ; SI指向已存密码BUF1 LEA DI,BUF2 ; DI指向本次输入BUF2 MOV CH,0 ; 清CH为CX赋值做准备 MOV CL,MSG11 ; CL 已存密码长度从MSG1第二字节读取 CMP CL,MSG21 ; 比较两个密码长度 JNZ WRONG ; 长度不同直接跳错误处理 REPZ CMPSB ; ZF1且CX0时匹配成功逐字节比较BUF1和BUF2 JZ RIGHT ; 匹配成功跳正确处理 WRONG: ; 错误处理 LEA DX,NO ; 显示PASSWORD ERROR$ MOV AH,9 INT 21H DEC BP ; 错误次数减1 JNZ SSS ; BP!0继续重试 STC ; 设置进位标志通知主程序退出 JMP OK ; 跳转到返回点 RIGHT: ; 正确处理 LEA DX,YES ; 显示PASSWORD CORRECT$ MOV AH,9 INT 21H OK: ; 统一返回点 MOV AH,1 ; 读一个字符暂停等用户按键 INT 21H RET逻辑说明与参数详解MOV BP,3用BP寄存器作为错误计数器初始值 3每次输错DEC BPJNZ SSS实现循环重试CMP CL,MSG21MSG11是已存密码长度MSG1 DB 255,0的第二字节MSG21是本次输入长度长度不等直接判错避免REPZ CMPSB越界REPZ CMPSB这是关键指令。“REPZ”表示“重复直到 ZF0 或 CX0”“CMPSB”比较DS:SI和ES:DI指向的字节并自动递增SI/DI。它要求CLD已执行确保SI/DI递增CX预置为比较长度此处MOV CL,MSG11DS:SI和ES:DI指向待比较内存BUF1和BUF2JZ RIGHTCMPSB结束后若ZF1所有字节相等且CX0比较完全部则跳RIGHTSTCJMP OK当BP0三次错误STC设置进位标志CF1主程序通过JC EXIT检测并退出。提示REPZ CMPSB的成功条件是ZF1 AND CX0仅ZF1不够如CX1时提前退出所以必须保证CX精确等于密码长度。3.4 退出机制INT 21H 功能号 4CH 的标准退出流程退出不是简单JMP $死循环而是调用 DOS 系统功能干净返回EXIT: LEA DX,MESG ; 加载退出提示PRESS ANY KEY TO EXIT ...$ MOV AH,9 INT 21H MOV AH,1 ; DOS读单字符功能阻塞等待按键 INT 21H MOV AH,4CH ; DOS退出程序功能返回DOSAX可设退出码 INT 21HMOV AH,4CH; INT 21H是 DOS 下程序退出的黄金标准。它会释放程序占用的内存恢复 DOS 环境比INT 20H更可靠INT 20H要求 PSP 在 CS:0而INT 4CH无此限制MOV AH,1; INT 21H是用户友好设计显示提示后暂停等用户按任意键再退出避免窗口一闪而逝MESG DB 0DH,0AH,0DH,0AH,9,PRESS ANY KEY TO EXIT ...$中的0DH,0AH,0DH,0AH是四次换行确保提示显示在屏幕中央区域9是 TAB 字符提供缩进。4. 编译、运行与调试在现代系统上复现 DOS 环境4.1 环境搭建DOSBox MASM 5.0 的黄金组合现代 Windows/macOS/Linux 无法原生运行 DOS 程序必须借助模拟器。DOSBox 是唯一推荐方案原因完美模拟 8086/8088 CPU、BIOS、DOS 中断向量支持INT 10H/INT 21H/INT 16H全功能体积小2MB启动快无兼容性问题。安装步骤Windows 为例下载 DOSBox 0.74官网 dosbox.com并安装下载 MASM 5.0经典版本非新版解压到C:\masm50创建工作目录C:\password将password.asm放入启动 DOSBox在命令行中执行mount c c:\password c: cd \4.2 编译命令详解ml.exe 与 link.exe 的参数含义在 DOSBox 中进入C:\password目录后执行以下两步ml /c /Zi password.asm link password.obj参数说明ml /c /Zi password.asm/c只编译不链接生成password.obj/Zi生成调试信息.cod文件便于用debug.exe单步跟踪link password.obj无参数使用默认链接脚本生成password.exe若报错LNK1181: cannot open input file password.obj确认ml是否成功执行检查当前目录是否有.obj文件。提示ml.exe和link.exe必须在 PATH 中或在C:\masm50\bin下运行。若路径未配置先执行path c:\masm50\bin;%path%。4.3 运行与交互主菜单的完整操作流编译成功后直接运行password程序行为显示主菜单5 行空行后居中显示带边框的MAIN MENU下方三个选项底部提示CHOICE(1,2,3):按1显示INPUT A STRING:光标闪烁输入密码如123456回车后返回主菜单按2显示ENTER YOUR PASSWORD:输入密码若与1中输入一致 → 显示PASSWORD CORRECT按任意键返回主菜单若不一致 → 显示PASSWORD ERROR自动重新提示输入连续输错三次 → 显示PRESS ANY KEY TO EXIT ...按任意键退出到 DOS按3直接显示退出提示按任意键退出。4.4 调试技巧用 debug.exe 查看寄存器与内存当程序行为异常如菜单不显示、输入无响应用 DOS 自带debug.exe单步调试debug password.exe -r ; 查看寄存器重点关注 AX, DX, AH -u 0100 ; 反汇编从 0100h 开始的代码DOS 加载后 CS:IP 通常为 0100h -t ; 单步执行一条指令 -d ds:0 ; 查看数据段开头内存检查 MENU 字符串是否加载正确 -q ; 退出 debug常见调试场景菜单不显示-r查AX若AX0000说明MOV AX,3; INT 10H未执行检查AGAIN标签前是否有跳转遗漏输入后无反应-d ds:offset MSG1查看MSG11是否为 0输入未写入确认INT 21H功能号 0AH 的缓冲区地址DX是否正确密码总判错-d ds:offset BUF1和-d ds:offset BUF2对比两个缓冲区内容确认REPZ CMPSB前CX是否等于密码长度。5. 避坑指南那些让我在 DOSBox 里熬通宵的血泪经验5.1 现象主菜单显示乱码如出现■、≡、█等符号边框不成形原因MENU字符串中混入了非 ASCII 扩展码或DUP()计算错误导致字符串未以$结尾。DOS 的INT 21H功能号 09H 会从DS:DX开始打印直到遇到$若$缺失或位置错误会越界打印内存垃圾。解决严格检查MENU定义确保每行字符串末尾都有$且DUP()数量准确。例如DB 25 DUP( ),201,21 DUP(205),187,0DH,0AH后必须跟$不能漏写。5.2 现象按1输入密码后返回主菜单时光标卡在提示符末尾新菜单覆盖旧文字原因LP1子程序末尾缺少光标归位指令。INT 21H功能号 0AH 输入后光标停在输入字符串末尾若不手动回车换行下次LEA DX,MENU; INT 21H会从该位置开始打印造成重叠。解决在LP1末尾添加MOV AX,0E0DH; INT 10H回车和MOV AL,0AH; INT 10H换行确保光标回到下一行首。5.3 现象密码校验永远失败即使输入完全相同原因REPZ CMPSB前未正确设置CX或CLD指令被意外覆盖。CMPSB依赖CX作为比较次数若CX0则不比较直接跳CLD被覆盖会导致SI/DI递减比较反向进行。解决在LP2开头确认CLD存在并在REPZ CMPSB前明确MOV CX,xxx如MOV CX,MSG11。用debug查CX值确保其等于密码长度。5.4 现象输错两次后程序崩溃或第三次错误不退出原因BP计数器逻辑错误。DEC BP后JNZ SSS跳转但若BP初始值非 3或中间被其他指令修改会导致计数不准。更严重的是STC后主程序未检测CF就JMP AGAIN造成无限循环。解决检查主循环中CP2分支的JC EXIT是否存在。原文中CALL LP2; JC EXIT是关键JC检测LP2中STC设置的进位标志若缺失此判断程序无法退出。5.5 现象在 Windows 10/11 的 64 位 CMD 中双击password.exe提示“不是有效的 Win32 应用程序”原因password.exe是 16 位 DOS 程序现代 Windows 64 位系统已移除 NTVDMNT Virtual DOS Machine子系统无法原生运行。解决必须使用 DOSBox。这是唯一可靠方案。不要尝试 Wine、VirtualBox 安装 DOS太重也不要找“DOS 兼容补丁”无效。DOSBox 启动后mount目录一切自然运行。6. 二次开发实战从课设到可用工具的五步改造6.1 改造一支持密码长度限制8-16 字符原程序无长度校验任何长度密码都接受。增加长度规则只需在LP1输入后插入检查; 在 LP1 的 INT 21H 后添加 LEA SI,MSG1 ; SI 指向输入缓冲区 MOV CL,[SI1] ; CL 实际输入长度 CMP CL,8 ; 最小长度8 JB LENGTH_ERR ; 小于8跳错误 CMP CL,16 ; 最大长度16 JA LENGTH_ERR ; 大于16跳错误 JMP LP1_DONE ; 合法继续 LENGTH_ERR: LEA DX,LEN_ERR ; PASSWORD LENGTH MUST BE 8-16!$ MOV AH,9 INT 21H JMP LP1 ; 重新输入 LP1_DONE: RET新增数据LEN_ERR DB 0DH,0AH,9,PASSWORD LENGTH MUST BE 8-16!$提示LEN_ERR必须以$结尾且LEA DX,LEN_ERR前确保DS正确。此改造让程序符合现代密码策略且代码仅增 10 行。6.2 改造二增加大小写字母与数字混合校验原程序只比内容不验字符类型。在LP2的RIGHT标签前插入类型检查; 在 JZ RIGHT 前添加 CHECK_TYPE: LEA SI,BUF1 MOV CX,MSG11 ; CX 密码长度 MOV BL,0 ; BL 小写字母计数 MOV BH,0 ; BH 大写字母计数 MOV DL,0 ; DL 数字计数 CHECK_LOOP: LODSB ; AL [SI], SI CMP AL,a JB NOT_LOWER CMP AL,z JA NOT_LOWER INC BL JMP NEXT_CHAR NOT_LOWER: CMP AL,A JB NOT_UPPER CMP AL,Z JA NOT_UPPER INC BH JMP NEXT_CHAR NOT_UPPER: CMP AL,0 JB NEXT_CHAR CMP AL,9 JA NEXT_CHAR INC DL NEXT_CHAR: LOOP CHECK_LOOP ; 检查是否至少各有一个 TEST BL,BL JZ TYPE_ERR TEST BH,BH JZ TYPE_ERR TEST DL,DL JZ TYPE_ERR JMP RIGHT ; 类型合法跳正确处理 TYPE_ERR: LEA DX,TYPE_MSG ; MUST CONTAIN UPPER, LOWER, DIGIT!$ MOV AH,9 INT 21H JMP SSS ; 重新输入新增数据TYPE_MSG DB 0DH,0AH,9,MUST CONTAIN UPPER, LOWER, DIGIT!$提示LODSB是MOV AL,[SI]; INC SI的简化指令高效遍历字符串。此逻辑确保密码必须含大小写字母和数字提升安全性。6.3 改造三将密码存储从明文改为简单异或加密原程序BUF1存明文存在泄露风险。添加异或加密密钥0x55; 在 LP1 的 INT 21H 后添加加密 ENCRYPT_LOOP: LEA SI,BUF1 MOV CX,MSG11 XOR_LOOP: XOR BYTE PTR [SI],55h ; 与0x55异或 INC SI LOOP XOR_LOOP解密在LP2的REPZ CMPSB前添加; 在 LEA SI,BUF1 后添加 DECRYPT_LOOP: LEA SI,BUF1 MOV CX,MSG11 XOR_LOOP2: XOR BYTE PTR [SI],55h INC SI LOOP XOR_LOOP2提示异或加密是实模式下最轻量的混淆方式XOR BYTE PTR [SI],55h一行指令完成不影响性能。6.4 改造四支持配置文件读取默认密码原密码需手动输入可改为从PASS.TXT文件读取。需调用INT 21H功能号 3Dh打开文件、3Fh读文件; 新增文件读取子程序 READ_PASS: MOV AH,3Dh ; 打开文件 MOV AL,0 ; 只读 LEA DX,PASS_FILE ; PASS.TXT INT 21H JC READ_ERR ; 打开失败 MOV BX,AX ; BX 文件句柄 MOV CX,16 ; 读16字节 LEA DX,BUF1 MOV AH,3Fh ; 读文件 INT 21H JC READ_ERR ; 成功CX 实际读取字节数存入 MSG11 MOV MSG11,CL CLOSE_FILE: MOV AH,3Eh ; 关闭文件 INT 21H RET READ_ERR: ; 错误处理设默认密码 LEA SI,DEF_PASS LEA DI,BUF1 MOV CX,8 COPY_DEF: MOVSB LOOP COPY_DEF MOV MSG11,8 RET PASS_FILE DB PASS.TXT,0 DEF_PASS DB DEFAULT1提示文件操作需注意INT 21H功能号 3Dh 要求文件名以0结尾非$且 DOS 下文件名必须是 8.3 格式。6.5 改造五添加日志记录功能记录成功/失败事件为调试和审计可将事件写入LOG.TXT。调用INT 21H功能号 3Ch创建文件、40h写文件; 在 RIGHT 和 WRONG 标签中添加 LOG_SUCCESS: LEA DX,SUCC_LOG ; LOGIN SUCCESS AT [TIME]$ JMP WRITE_LOG LOG_FAIL: LEA DX,FAIL_LOG ; LOGIN FAIL AT [TIME]$ WRITE_LOG: MOV AH,3Ch ; 创建/打开文件 MOV CX,0 ; 属性普通文件 LEA DX,LOG_FILE INT 21H JC LOG_SKIP MOV BX,AX ; BX 句柄 MOV CX,2 p a hrefhttps://download.csdn.net/download/blackpipi1/4951192 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑