DOS系统调用总汇

Author: Date: 1991-12-27

        一、概要说明
        图1列出了五个DOS中断功能,其中,中断21H最有用,它提供了访问几乎全部DOS功能的通用入口。中断25H和26H,绝对磁盘读/写接口,常用于需要绕过DOS文件接口的情况。剩下的中断,20H和27H,是DOS版本1提供的程序终止和驻留服务,此功能在DOS版本2.0提供中断21H后已废弃。
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        中断
        十六进制       十进制       说   明
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        20H 32       程序终止:正常结束
        21H 33       一般DOS调用
        25 3       绝对磁盘读
        26H 38       绝对磁盘写
        27H 39       终止并驻留
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
          图1 五个主要的DOS中断
        图2详细列出了DOS版本1提供的并为所有更高版本支持的中断21H功能。
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        功能
        十六进制       十进制       说   明
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        00H       0              程序终止
        01H             1               带回显的字符输入
        02       2               字符输出
        03H       3             辅助输入
        04H       4               辅助输出
        05H       5               打印机输出
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        图2 所有DOS版本提供的中断21H功能
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        06H       6输入/输出
        07H             7               不带回显的直接字符输入
        08H       8               带回显的字符输入
        09H       9               串输出
        0AH       10       键盘缓冲输入
        0CH       12       刷新键盘缓冲区,读键盘
        0DH       13       刷新磁盘缓冲区
        0EH       14       选择磁盘驱地劝器
        0FH       15       打开文件
        10H       16       关闭文件
        11H       17       搜索第一个相匹配的目录入口
        12H       18       搜索下一个相匹配的目录入口
        13H       19       删除文件
        14H       20       顺序读
        15H       21       顺序写
        16H       22       创建文件
        17H       23       修改文件名
        19H       25       取当前磁盘号
        1AH       26     设置数据传送区(Datav Trannfer Area)地址       1BH       27       取缺省磁盘信息
        1CH       28       取指定磁盘信息
        21H       33       随机读记录
        22H       34       随机写记录
        23H       35       取文件大小
        24H       36       设置文件控制块(File Contorl Block)随                                      机记录字段
        25H       37       设置中断向量
        26H       38       创建新的程序段前缀                                      (Program SegmentPrefix)
        27H         39       随机读记录块
        28H         40       随机写记录块
        29H       41       分析文件名
        2AH       42       取日期
        2BH       43       设置日期
        2CH       44       取时间
        2DH       45       设置时间
        2EH       46       设置校验标志
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        图3列出了DOS版本2.0提供的并为以后版本扩充的扩展中断21H功能集。
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        功能
        十六进制      十进制      说    明       DOS版本
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        2FH       47 取数据传送区地址      2.0
        30H       48 取DOS版本号       2.0
        31H       49 终止并驻留       2.0
        33H       51 设置/取Ctrl-c标志     2.0
        35H       53 取中断向量       2.0
        36H       54 取磁盘自由空间容量    2.0
        38H       56   设置/取指定国家有关的信息  2.0
        39H       57 创建目录       2.0
        3AH       58 删除目录       2.0
        3BH       59 改变当前目录       2.0
        3CH       60 创建文件       2.0
        3DH       61 打开文件       2.0
        3EH       62 关闭文件       2.0
        3FH       63 从文件或设备读       2.0
        40H       64 向文件或设备写       2.0
        41H       65 删除文件       2.0
        42H       66 移动文件指标       2.0
        43H       64 设置/取文件属性       2.0
        44H       68 IOCTL_设备输入/输出控制  2.0
        46H       69 复制文件名柄       2.0
        46H       70 强行复制文件名柄      2.0
        47H       71 取当前目录       2.0
        48H       72 分配内存块       2.0
        49H       73 释放内存块       2.0
        4AH       74 修改内存块大小        2.0
        4BH       75 装入并执行程序       2.0
        4CH       76 终止过程并给出返回码  2.0
        4DH       77 取返回码              2.0
        4EH       78 搜索第一个相匹配的目录入口    2.0
        4FH             79 搜索下一个相匹配的目录入口    2.0
        54H       84 取校验标志       2.0
        56H       86 修改文件名       2.0
        57H       87 设置/取文件日期和时间 2.0
        58H       88 设置/取内存分配策略   3.0
        59H       89 取已扩充的错误信息    3.0
        5AH       90 创建暂时文件          3.0
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        功能
        十六进制      十进制      说    明       DOS版本
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        5BH       91 创建新文件       3.0
        5CH       92 封锁/解锁文件访问区   3.0
        5EH       94 网络机器名和打印机设置 3.1
        5FH       95 网络再定向       3.1
        62H             98 取程序段前缀       3.0
        65H       101 取扩展的国家信息      3.3
        66H       102 设置/取全局代码页     3.3
        67H       103 设置/取全局代码页     3.3
        67H       103 设置文件句柄计数      3.3
        68H       104 提交文件             3.3
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        通过调用中断21H可使用所有的中断21H功能。使用时,在寄存器AH中存放功能编号,其它参数需要时放在8086的其它寄存器中;大多数DOS功能在AL或AX中返回一完成码;  DOS版本2.0以后提供的大部分功能也常用进位标志回送功能调用成功标志。
        二、详细列表
        上面我们简要地列出了所有的DOS功能,以便通过功能编号能方便地查到各项功能。这一部分,我们将详细列出使用中断21H功能时的寄存器值的变化情况(即使用该中断时,寄存器送往中断21H的值和从中断21H返回寄存器的值)。
        由于很多DOS新版本提供了一些以前版本没有的功能,因此我们在介绍功能时标明了其DOS版本号。
        DOS中断21H功能总汇
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        功能编号            寄存器              DOS
        中断服务   (十六进制)  输入   输出      版本号    注释
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        1. 程序控制功能
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━     终止:
        结束程序 00H   AH=00H 1.0已过时:用功能4CH代替
               CS=PSP的段地址
        ───────────────────────────────────
        创建新程
        序段 26H AH=26H 1.0已过时:用功能4BH代替
         DX=新PSP开始的段地址
        ───────────────────────────────────
        终止并驻
        留 31H AH=31H 2.0
         AL=返回码
         DX=驻留内存段的段号
        ───────────────────────────────────
        设/取Ctrl-C
        标志 33H AH=33H  设标志:AL=01H DL=标志值 取标志:
         AL=00H AL=结果码若调用时  AL=01H,则DL=当前标志值(0= OFF,1=ON) 2.0
        ───────────────────────────────────
        EXEC:装入并执行程序 4BH  AH=4BH DS∶DX→ASCIIZ
         命令行段:位移ES:BX→控制块执行子程序段:
         AL=00H 装入而不执行:AL=03H 若无错,则:清CF位;若出错,则: 置CF位,AX=错误码;
         2.0修改包括SS∶SP在内的所有寄存器
        ───────────────────────────────────
        终止过程并给出返回码 4CH AH=4CH AL=返回码 2.0
        取返回码 4DH AH=4DH   AL=返回码 AH=终止方法   2.0调用功能4CH            后只能调用一次
        ───────────────────────────────────
        取PSP地址 62H AH=62H   BX=PSP段地址 3.0
        ───────────────────────────────────
        2.标准输入/输出功能
        ───────────────────────────────────
        带回显的字符输入       01H   AH=01H  AL=8位字符 1.0
        不带回显的直接字符输入 07H   AH=07H   AL=8位字符 1.0
        不带回显的字符输入     08H   AH=08H  AL=8位字符 1.0
        键盘缓冲输入          0AH   AH=0AH   DS∶DX→输入缓冲区段:位移
         缓冲区存放键盘输入字符 1.0输入缓冲区格式
        ───────────────────────────────────
        检测键盘状态          0BH    AH=0BH   若有字符输入:AL=FFH;若无字符输入 :AL=00H 1.0
        ───────────────────────────────────
        刷新键盘缓冲区,读键盘  0CH    AH=0CH   AL=功能编号(01H,06H,07H,08H,或  0AH) 取决于AL中指定的功能 1.0
        ───────────────────────────────────
        字符输出  02H AH=02H   DL=8位字符 1.0
        ───────────────────────────────────
        串输出  09H AH=09H   DS∶DX→  结束的串据在段:位移 1.0   ────────────────────────────────────
        3.主控台I/O控制
        ────────────────────────────────────
        直接字符输入/输出 06H AH=06H输入一字符:DL=FFH输出一字符:
         DL=8位字符(00H_FEH) 如果用DL=FFH调用, 则:AL=8位字符 1.0
        ────────────────────────────────────
        4.各种I/O控制
        ────────────────────────────────────
        辅助输入 03H AH=03H     AL=8位字符 1.0
        辅助输出 04H AH=04H     DL=字符 DL=字符 1.0
        打印机输出 05H AH=05H 1.0
         DL=字符
        ────────────────────────────────────
        5.磁盘功能
        ────────────────────────────────────
        刷新磁盘缓冲区 0DH AH=0DH 1.0见功能68H
        ───────────────────────────────────
        选择磁盘驱动器 0EH AH=0EH DL=驱动器ID AL=系统驱驱动器号
         1.0对于DOS3.0及其后版本,AL>=05H
        ───────────────────────────────────
        取当前磁
        盘号 19H AH=19H AL=驱动器ID 1.0
        ───────────────────────────────────
        设置DTA地址 1AH AH=1AH DS∶DX→DTA所在段:位移 1.0
        ───────────────────────────────────
        取缺省驱动器信息 IBH AH=1BH AL=每簇包含的扇区数
          CX=每扇区包含的字节数 DX=磁盘的总簇数
          DS∶BX→FAT标识字节段:位移
          1.0已过时,用功能36H代替
        ───────────────────────────────────
        取指定驱动器信息 ICH   AH=1CH DL=驱动器标志   AL=每簇包含的扇区数  CX=每扇区包含的字节数 DX=磁盘的总簇数
         DS∶BX→介质标志字节 已过时,用功能1.0 36H代替
        ───────────────────────────────────
        设置校验标志         2EH AH=2EH AL=标志值(0=off,1=on)DL=00H 1.0 DOS 3.0以前的版本用DL=00H调用
        ───────────────────────────────────
        取DTA地址 2FH AH=2FH ES∶BX→DTA 2.0
        ───────────────────────────────────
        取磁盘自由空间 36H AH=36H DL=驱动器ID 如果驱动器ID错:
         AX=FFFFH;如果无错:AX=每簇包含的扇区数BX=未使用过 的簇数CX=每扇区包含的字节数DX=磁盘总簇数   2.0
        ───────────────────────────────────
        取校验标志 54H AH=54H AL=标志值(0=off,1=9n)     2.0
        ────────────────────────────────────
        6.文件管理功能
        ────────────────────────────────────
        删除文件 13H AH=13HDS∶DX→FCB 若有错:AL=FFH,若无错:
         AL=00H 1.0已过时,用功能41H代替
        ───────────────────────────────────
        创建文件 16H AH=16H DS∶DX→FCB所在段:位移 若有错:AL=FFH;
         若无错:AL=00H 1.0已过时,用功能3CH5AH,或5BH代替
        ───────────────────────────────────
        修改文件 17H AH=17HDS∶DX→已修改过的FCB所在段:位移
         若有错:AL=FFH;若无错:AL=00H 1.0已过时,用功能56H代替
        ───────────────────────────────────
        取文件大小 23H AH=23HDS∶DX→FCB所在段:位移 若有错:AL=FFH;
         若无错:AL=00H FCB含文件大小信息  1.0已过时,用功能42H代替
        ───────────────────────────────────
        分析文件名 29H AH=29H AL=控制位DS∶SI→被分析串的段:位移
         ES∶DI→FCB所在段:位移 AL=错误码DS∶SI→被分析串的后一字 符所在段:位移ES∶DI→FCB所在段:位移 1.0不能分析路径
        ───────────────────────────────────
        创建文件 3CH AH=3CH CX=属性  DS∶DX→ASCIIZ文件说明表所 在段:位移 若有错:置CF,AX=错误码;若无错:
         清CF AX=文件句柄 2.0
        ───────────────────────────────────
        删除文件 41H AH=41H   DS∶DX→AXCIIZ文件说表明表所在段:位移
         若有错:置CF,AX=错误码;若无错:清CF 2.0
        ───────────────────────────────────
        设置/取文件属性  43H AH=43H   DS∶DX→ASCIIZ文件说明表所在段:位移 取文                   件属性:AL=00H 设文件属性:AL=01H CH=属性 若有错:置                     CF,AX=错误码;   若无错:清CF,CX=属性(如调用时AL=00H)                    2.0
        ───────────────────────────────────
        修改文件名 56H AH=56H DS∶DX→原有ASCIIA文件说明表所在段:位移
         ES∶DI→新ASCIIZ文件说明表所在段:位移
         若有错:置CF,AX=错误码 若无错:清CF
         2.0可用于将一文件从一个目录移到另一目录
        ───────────────────────────────────
        设置/取文件日期和时间   57H AH=57H BX=文件句柄取日期和时间:AL=00H设 置日期和时间:AL=01H CX=时间 DX=时期 若有错:置CF,AX=错 误码;若无错:清CF;如调用时AL=00H,则:CX=时间 DX=时期    2.0
        ───────────────────────────────────
        创建临时文件 5AH AH=5AH CX=属性 DX∶DX→后加13个空字节的ASCIIZ路径 所在段:位移 若有错:置CF,AX=错误码;若无错:清CF,AX=文件 句柄DS∶DX→ASCIIZ文件说明表所在段:位移 3.0
        ───────────────────────────────────
        创建新文件 5BH AH=5BH CX=属性 DS∶DX→ASCIIZ 文件说明表所在段:位 移  若有错:置CF,AX=错误码;若无错清CF,AX=文件句柄    3.0
        ────────────────────────────────────
        7.文件输入/输出功能
        ────────────────────────────────────
        打开文件 0FH AH=0FH DS∶DX→FCB所在段:位移 AL=返回码  1.0已过 时,用功能3DH代替
        ───────────────────────────────────
        关闭文件 10H AH=10H DS∶DX→FCB所在段:位移 AL=返回码
         用功能3EH代替
        ───────────────────────────────────
        顺序读 14H AH=14H DS∶DX→FCB所在段:位移 AL=返回码DTA含读出 数据1.0已过时,用功能3FH代替  顺序写                 15H AH=15H DS∶DX→FCB所在段:位移DTA含待写数据
         AL=返回码 1.0已过时,用功能40H代替
        ───────────────────────────────────
        随机读记录 21H AH=21H DS∶DX→FCB所在段:位移 AL=返回码 DTA含读 出数据 1.0已过时,用功能3FH代替
        ───────────────────────────────────
        随机写记录 22H AH=22H DS∶DX→FCB所在段:位移DTA含待写数据
         AL=返回码 1.0已过时,用功能40H代替
        设PCB随机记录字段 24H AH=24H DS∶DX→FCB所在段:位移 AL=00H FCB含已更新 的随机记录字段 1.0已过时,用功能42H代替
        ───────────────────────────────────
        读随机记录块 27H AH=27H CX=记录数  DS∶DX→FCB所在段:位移
         AL=返回码 CX=读出的记录数 DTA含读出数据   1.0已过时,     用功能3FH代替
        ───────────────────────────────────
        写随机记录块 28H AH=28H CX=记录数 DS∶DX→FCB所在段:位移DTA含要写 的数据 AL=返回码CX=已写的记录数 1.0已过时,用功能40H 代替
        ───────────────────────────────────
        打开文件句柄 3DH AH=3DH AL=文件访问码 DS∶DX→ASCIIZ文件说明表所在 段:位移 若有错:置CF,AX=错误码;若无错:清CF,AX=文件句柄 2.0  关闭文件句柄 3EH AH=3EH BX=文件句柄 若有错:置CF AX=错误码:若无 错:清CF 2.0
        ───────────────────────────────────
        从文件或设备读  3FH AH=3FH BX=文件句柄 CX=要读的字节数DS∶DX→缓冲区   所在段:位移 若有错:置CF位 AX=错误码;若无错:清CF AX=读   出的字节数 DS∶DX→缓冲区所在段:位移 2.0
        ───────────────────────────────────
        向文件或设备写 40H AH=40H BX=文件句柄 CX=要写的字节数 DS∶   DX→缓冲区所在段:位移 若有错:置CF AX=错误码:若无错:清CF    AX=已写的字节数 2.0
        ───────────────────────────────────
        移动文件指针   42H AH=42H BX=文件句柄 CX∶DX=移动指针的偏移量移到文   件开始位置:AL=00H移到当前位置:AL=01H移到文件尾:AL=02H   若有错:置CF AX=错误码;若无错:清CF DX∶AX=新文件指针所在   段:位移 2.0
        ───────────────────────────────────
        复制文件句柄   45H AH=45H BX=文件句柄 若有错:置CF AX=错误码;若无   错:清CFAX=新文件句柄 2.0
        ───────────────────────────────────
        强行复制文件句柄 46H AH=46H BX=文件句柄 CX=被复制的文件句柄  若有错:   置CF AX=返回码;若无错:清CF 3.0
        ───────────────────────────────────
        封锁/解锁文件区  5CH  AH=5CH BX=文件句柄 CX∶DX=将要封锁/解锁的文件区   之首地址所在段:位移SI∶DI=封锁/解锁的文件区大小要封锁文                  件区:AL=00H要打开文件区:AL=01H   若有错:置CF AX=错误码   :若无错:清CF 3.0与SHARE一齐用或在网络环境下用
        ───────────────────────────────────
        设置句柄记数器  67H AH=67H BX=文件句柄数若有错:置CF AX=错误码:若无错   :清CF 3.3
        ───────────────────────────────────
        提交文件        68H AH=68H BX=文件句柄 若有错:置CF,AX=错误码;若无   错:清CF 3.3
        ────────────────────────────────────
        8.目录功能
        ────────────────────────────────────
        搜索第一个相匹配的目录入口 11H AH=11H DS∶DX→FCB所在段:位移 若 有错:AL=FFH;若无错:AL=00H DTA含目录信息 1.0已过时,用功能4EH代替
        ───────────────────────────────────
        搜索下一个相匹配的目录入口 12H AH=12H DS∶DX→FCB所在段:位移 若 有错:AL=FFH;若无错:AL=00H DTA含目录信息 1.0已过时,用功能4FH代替
        ───────────────────────────────────
        创建目录 39H AH=39H DS∶DX→ASCIIZ路径所在段:位移  若有错:置CF  AX=错误码;若无错:清CF 2.0
        ───────────────────────────────────
        删除目录 3AH AH=3AH DS∶DX→ASCIIZ路径所在段:位移若有错:置CF AX =错误码:若无错:清CF 2.0
        ───────────────────────────────────
        取当前目录 47H AH=47H DL=驱动器ID DS∶SI→64个字节的空缓冲区所在 段:位移 若有错:置CF AX=错误码;若无错:清CF DS∶SI→ASCIIZ路 径所在段:位移 2.0
        ───────────────────────────────────
        搜索第一个相匹配的目录入口 4EH AH=4EH CX=属性 DS∶DX→ASCIIZ文件 说明表所在段:位移   若有错:置CF AX=错误码;若无错:清CF DTA 含目录信息 2.0
        ───────────────────────────────────
        搜索下一个相匹配的目录入口 4FH AH=4FH DT含从上一次调用4EH或4FH中                  得到的信息   若有错:置CF AX=错误码;若无错:清CF DTA                        含目录信息 2.0
        ────────────────────────────────────
        9.日期/时间功能
        ────────────────────────────────────
        取日期 2AH AH=2AH AL=星期几 CX=年 DH=月 DL=日    1.0
        ───────────────────────────────────
        设置日期 2BH AH=2BH CX=年 DH=月 DL=日 若有错:AL=FFH;若无 错:AL=00H 1.0
        ───────────────────────────────────
        取时间 2CH AH=2CH CH=小时 CL=分 DH=秒 DL=1/100秒
        ───────────────────────────────────
        设置时间 2DH AH=2DH CH=小时 CL=分 DH=秒 DL=1/100秒  若有错 :AL=FFH 若无错:AL=00H 1.0
        ────────────────────────────────────
        10.其它各种功能有
        ────────────────────────────────────
        设置中断向量 25H AH=25H AL=中断号 DS∶DX→指定中断向量的分段地址 1.0
        ───────────────────────────────────
        取DOS版本号 30H AH=30H AH=辅版本号 AL=主版本号 BX,CX=连续号 2.0DOS版本1.0返回AL=00HOS/兼容寄存器返回AL=0AH
        ───────────────────────────────────
        取中断向量 35HAH=35H AL=中断号 ES∶BX=指定的中断向量的内容 1.0   ───────────────────────────────────
        设置/取与指定国家的有关信息 38H AH=38H AL=国家代号或FFH BX=国家 代号(若AL=FFH);取国家信息:DS∶DX→34字节长的空缓冲区所在段 :位移设国家信息:DX=FFFFH 若有错:置CF位 AX=错误码;若 无错:清CF位;若调用时DX<>FFFFH,则:BX=国家代码DS∶DX→国家 信息 2.0DX=FFFFH和AL=FFH的调用只有DOS3.0及以后的版本支 持见功能65H。
        ───────────────────────────────────
        IOCTL 44H AH=44H AL=子功能号(其余寄存器值视子功能号而定) 若有错:置CF位AX=错误码;若无错:清CF位(其余寄存器值视子功能        号而定)
        ───────────────────────────────────
        取已扩充的错误信息 59H AH=59H BX=00H AX=扩展错误码 BH=错误类型  BL=建议动作 CH=错误定位     3.0改变CL,DX,SI,DI,ES和DS的值   ───────────────────────────────────
        网络机器名和打印机设置 5EH AH=5EH AL=子功能号(其它寄存器的值视子功能                        而定) 若有错:置CF位AX=错误码:若无错:清CF位(其它                   寄存器的值视子功能号而定) 3.1只适用于网络环境
        ───────────────────────────────────
        网络重定向 5FH AH=5FH AL=子功能号(其余寄存器值视子功能号而定) 若有错:置CF位AX=错误码;若无错:清CF位(其余寄存器值视子功能             号而定) 3.1只适用于网络环境
        ───────────────────────────────────
        取扩展的国家信息 65H AH=65H AL=信息ID码BX=代码页号 CX=缓冲区 长度DX=国家ID码ES∶DI→缓冲区所在段:位移   若有错:置CF位AX =错误码;若无错:清CF位ES∶DI→扩展的国家信息所在段:位移 3.3
        ───────────────────────────────────
        设置/取全局代码页 66H AH=66H要取当前代码页:AL=01H要设置当前代码                页:AL=02H BX=代码页号 若有错:置CF位 AX=错误码;若                       无错:清CF位;  若用AL=01H调用,则:BX=当前代码页 DX=                       缺省代码页           3.3
        ────────────────────────────────────
        11.内存功能
        ────────────────────────────────────
        分配内存块 48H AH=48H BX=段内块大小若有错:置CF位 AX=错误码 BX=              可用块的最大容量;若无错:清CF位 AX=已分配块的段地址  2.0
        ───────────────────────────────────
        释放内存块 49H AH=49H ES=内存块的段地址    若有错: 置CF位AX=错
         误码;若无错:清CF位 2.0
        ───────────────────────────────────
        改变内存块大小 4AH AH=4AH BX=段内内存块大小的新值ES=内存块的段地址 若有错:置CF位AX=错误码 BX=可用块的最大容量(若需增加容量);          若无错:清CF位 2.0
        ───────────────────────────────────
        设/取内存分配策略  58H    AH=58H取内存分配策略:AL=00H设置分存分配策略 :AL=01H BX=策略代码 若有错:置CF位AX=错误码;若无错:清CF 位;若调用时AL=00H,则:AX=策略代码 3.0
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━