Misaka-xxw的博客

昨日种种,皆成今我

一边使用,一边记录。

下载安装

windows

官网下载位置:https://www.gyan.dev/ffmpeg/builds/
按Ctrl-F,找到ffmpeg-release-essentials.zip,下载解压
设置环境变量为“【ffmpeg-release-essentials所在的路径】/bin”

linux

ubuntu

1
sudo apt install FFmpeg

其它:https://linux.cn/article-14716-1.html

使用

将某一文件夹的flac文件全部转化成wav文件

假设参数:16位PCM,采样率为44100Hz,双声道

1
for %%f in (*.flac) do (ffmpeg -i "%%f" -acodec pcm_s16le -ar 44100 -ac 2 "%%~nf.wav")

检查无误,批量删除原flac文件
如果要进行确认,就不加/q
1
del /q *.flac

提高亮度或者对比度

1
2
ffmpeg -i in.png -vf "eq=brightness=0.1" out.png 
ffmpeg -i in.png -vf "eq=brightness=0.1:contrast=1.1" out.png

其中亮度的基准为0,对比度的基准为1.0

将MP4视频去掉音频

1
ffmpeg -i input.mp4 -c:v copy -an output.mp4

将MP4视频每秒6帧转为800x480的bmp图片

1
ffmpeg -i input.mp4 -f image2 -vcodec bmp -s 800x480 -r 6 %d.bmp

C语言复习过几遍,所以这里记录一些有点难记的东西。

数据类型

大小

  1. 整数类型:
    short 2字节
    int 4字节
    long 8字节

  2. 浮点类型:
    double 8字节
    float 4字节
    定义float类型时需写成:float num = 0.5f;(小数默认是double)

  3. 字符类型:
    char 1字节
    可以表示ASCLL码中所有的字符,不能表示中文等

占位(p73)

%占位:
printf格式化输出函数,%占位时有以下参数:%[占位长度][.精确位数(四舍五入)]占位格式

  • %d 为整数占位
  • %hd 为short整数占位
  • %ld 为long整数占位
  • %u 为unsigned整数占位
    %lu,%hu..
    对unsigned赋值负数,补码的首位依然被认为是1,但输出时这个1是会带入二进制计算的
  • %e 指数
    例:printf("%e",123.456); 输出:1.234560e+002
    例:printf("%13.2e",123.456); 输出:(四个空格)1.23e+002
  • %E %e的大写
  • %i 等同于%d
  • %o 八进制输出
  • %x 十六进制输出,小写
  • %X 十六进制输出,大写
  • %g 自动选择%f或者%e输出,小写
  • %G 自动选择%f或者%E输出,大写
  • %s 字符串

科学计数法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int main()
{
printf("%lf\n", 123000000.0); // 123000000.000000
printf("%.2e\n", 123000000.0); // 1.23e+008
printf("%.2e\n", -123000000.0); //-1.23e+008
printf("%lf\n", 0.0000000123); // 0.000000
printf("%e\n", 0.0000000123); // 1.230000e-008
printf("%g\n", 0.0000000123); // 1.23e-008
printf("%.2e\n", 0.0000000123); // 1.23e-008
printf("%.2e\n", -0.0000000123); //-1.23e-008
printf("%lf, %e\n", .1e-2, .1e-2); // 0.001000, 1.000000e-003
return 0;
}

舍入舍出

浮点型格式化输出,四舍五入:

1
2
float a;
printf("%f\t%.2f\n", a, a);

浮点型强制转化,直接丢小数点后的

1
printf("%f\t%d\n", a, (int)a);

转义字符

转义字符 字符值
\'
\"
\? ?
\\ \
\a 警告
\b 退格
\f 换页
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
\o、\oo、\ooo,o代表一个八进制数字 与该八进制码对应的ASCLL字符
\xh[h..],h代表一个十六进制数字 与该十六进制码对应的ASCLL字符

ASCII码

常见ASCII码:
‘ ‘: 32
‘0’: 48
‘A’: 65
‘a’: 97

运算符

优先级 运算符 含义 运算对象个数 结合方向
1 ( ) →👉
[ ]
->
.
2 ! 1 ←👈
~
++
--
-
(类型)
*
&
sizeof
3 * 2 →👉
/
%
4 + 2 →👉
-
5 << 2 →👉
>>
6 < <= > >= 2 →👉
7 == 2 →👉
!=
8 & 2 →👉
9 ^ 2 →👉
10 | 2 →👉
11 && 2 →👉
12 || 2 →👉
13 ? : 3 ←👈
14 = += -= *= /= %= >>= <<= &= ^= |= 2 →👉
15 , →👉

文件操作

1. 文件类型指针

(p333)

用纸质笔记记录了。准备在C语言期末笔记(二)里面写

文件操作例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
int main()
{
FILE *fp;
int e;
long len;
char c;
int status;
fp = fopen("pi.tmp", "w");
fputs("3.1415926", fp); // len=8,SEEK_SET=>0,SEEK_END=>9
fclose(fp);
fp = fopen("pi.tmp", "r");
fscanf(fp, "%d%c", &e, &c);
printf("e=%d,c=%c\n", e, c); // e=3,c=.

//=============== fseek & ftell test start ===============
len = ftell(fp);
printf("before fseek:%ld\n", len); // 2,指向'1'之前
status = fseek(fp, -1L, SEEK_END);
printf("fseek -1 end:%ld (%d)\n", ftell(fp), status); // 8
rewind(fp); // void函数,没有返回值
printf("rewind:%ld\n", ftell(fp)); // 0
status = fseek(fp, -1L, SEEK_SET);
printf("fseek -1 set:%ld (%d)\n", ftell(fp), status); // 0,fseek失败
status = fseek(fp, 111L, SEEK_SET);
printf("fseek 111 set:%ld (%d)\n", ftell(fp), status); // 111,虽然比文件长了很多,但是fseek成功
status = fseek(fp, -121L, SEEK_CUR);
printf("fseek -121 cur:%ld (%d)\n", ftell(fp), status); // 111,fseek失败
status = fseek(fp, -111L, SEEK_CUR);
printf("fseek -111 cur:%ld (%d)\n", ftell(fp), status); // 0
}

例题

魔法阵

思路

第一排:if is middle: init 1;
else: {row = a - 1;//
col++;//→}
右上角:row++;//↓
row--;//↓
col++;//→
row--;//↓
col++;//→
最右列:
row--;//↑
col = 0;//|←
row--;//↓
col++;//→
row--;//↓
col++;//→
1
2
3
if 已占数字:
row = (row + 2) % a;//→→2,超出则|←
col = (col + a - 1) % a;//←1,超出则→|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <stdio.h>
#include <string.h>
int main()
{
int n = 3, num, row, col, a, a2;
int arr[101][101];
for (a = 1; a <= n; a+=2)
{
memset(arr, 0, sizeof arr);
row = 0;
col = a / 2;
a2 = a * a;
for (num = 1; num <= a2; num ++)
{
// printf("row: %d col: %d num: %d\n",row,col,num);
arr[row][col] = num;
if (row == 0 && col == a - 1)
{
row++;
}
else if (row == 0)
{
row = a - 1;
col++;
}
else if (col == n - 1)
{
row--;
col = 0;
}
else
{
row--;
col++;
}
if (arr[row][col] != 0)
{
row = (row + 2) % a;
col = (col + a - 1) % a;
}
}
for (row = 0; row < a; row++)
{
for (col = 0; col < a; col++)
{
printf("%2d ", arr[row][col]);
}
putchar('\n');
}
putchar('\n');
}
return 0;
}

易错点

  • 默认输出六位

    1
    printf("%f",f);
  • 反常识define

    1
    2
    #define true 0
    #define false 1
  • switchbreak就继续走

  • fseek(fp, 0L, 2);中,最后那个才是指示从哪儿开始的,即SEEK_END=2

第二章

  • 小阶向大阶对齐的原因:
    减小误差
  • 什么叫溢出?
    超出了机器的表示范围
  • 计算机内部为什么大部分
  • 全加器公式

  • 全加器的时间延迟
  • 行波进位补码加法器为什么m=0为加法,m=1为减法?
  • 默写对2求补电路

alt text

  • 直接补码阵列乘法器
    最高位权值-1
  • 间接补码阵列乘法器
    算前求补的目的:补码变原码,扣掉符号位
    算后求补的目的:原码变补码,存入计算器
  • 原码除法:符号位单独运算
  • 阵列除法器CAS用的是加减交替法
  • ALU电路的基本概念
  • 先行进位
  • 流水线特点:并行进行运算,速度快

[x]补+[y]补=[x+y]补的证明

补码加法的公式为:

</span>

证明:设x和y均为定点小数,且运算结果没有溢出。即

  • (1)x﹥0,y﹥0,则x+y﹥0。正数的补码和原码是一样的,可得:

[x]补+[y]补=x+y=[x+y]补 (mod 2)

  • (2)x﹥0,y﹤0,x+y≥0或x+y﹤0。
    [x]补=x,
    [y]补=2+y
    [x]补+[y]补=x+2+y=2+(x+y)
    • 当x+y≥0时,2 +(x+y) ≥2,对于模2来说,2被丢掉,于是
      [x]补+[y]补=x+y=[x+y]补 (mod 2)
    • 当x+y﹤0时,2 +(x+y) ﹤2,于是
      [x]补+[y]补=2+(x+y)=[x+y]补
      (mod 2)
  • (3)x﹤0,y﹥0。
    这种情况和第2种情况证明方法相同。
  • (4)x﹤0,y﹤0,则x+y﹤0。
    [x]补=2+x,
    [y]补=2+y
    [x]补+[y]补=2+x+2+y=2+(2+x+y)
    (2+x+y) 小于2而大于1的数,第一个2作为进位被舍弃。于是
    [x]补+[y]补=2+(x+y)=[x+y]补 (mod 2)
    至此我们证明了在模2意义下,两数的补码之和等于这两个数之和的补码。

第三章

  • 高速缓冲存储器cache的目的
    提升访问速度,使存取速度和CPU的运算相匹配
  • 双译码结构优点
    减少线的数目
  • 刷新->行
  • 地址复用技术
  • CDRAM DRAM里放一个SRAM
    SRAM->静态存储器,比较小但快
    DRAM->动态存储器
    读取时高位不变,低9位连续变化
    在SRAM读出期间同时对DRAM阵列进行刷新
    写和读可以同时
  • SDRAM:同步DRAM-CPU在SDRAM执行请求CPU同时,CPU能先去做别的
  • DDR SDRAM:上升沿和下降沿均可读数据
  • SRAM和DRAM
SRAM DRAM
存储容量
功率
速度
集成率
价格 便宜
缓冲 高速缓冲 需要定期刷新
  • 解决CPU和贮存之间速度差异的主要途径
    • CPU内部设置更多通用寄存器
    • CPU和主存之间插入高速缓冲存储器(cache)
    • 采用并行操作的存储器(如双端口存储器)
    • 主存储器采用更高速的技术来缩短读出时间,或加长存储器的字长
  • 相连存储器:按内容访问所有存储器,主要用来存放cache的行地址
  • 程序局部性:时间局部性和空间局部性
    • 时间局部性:如果一个存储单元被访问,则可能该单元会很快被再次访问(因为程序存在着循环)
    • 空间局部性:如果一个存储单元被访问,则该单元邻近的单元也可能很快被访问。(因为程序中大部分指令是顺序存储、顺序执行的,数据也是以向量、数组、树、表等形式簇聚地存储在一起的。)
  • 主存与cache的地址映射(p94)
    • 全相联映射方式
    • 直接映射方式
    • 级相连映射方式
  • cache的替换策略(p100)
    • 最不经常使用(LFU)算法
    • 近期最少使用(LRU)算法
    • 随机替换

主存与cache的地址映射(p94)

全相联映射方式 直接映射方式 组相联映射方式
主存地址长度 (s+w)位
页内地址 w位
寻址单元数 2s+w
块大小 2w
行大小
主存的块数 2s
标记位数 s位 (s-r)位 (s-d)位
组内块号 r位 d位
cache的行数 不由地址格式确定 m=2r m=uv
主存区内块号 cache行号 cache组号
每组的行数 v
cache的组数 u=2d

PPT例题

一个四路组相联的Cache共有64行,主存有8192块,每块32个字,则主存地址中的主存字块标记(tag)为_位,组地址(组号)为_位,字块内地址为___位。
v=4
m=64=uv =>u=16
u=2^d => d=4
2^w=32 => w=5
2^s=8192=2^13 => s=13
∴ans: 9 4 5

某8位机主存1M字节,分成512块,Cache分8行,地址采用全相联映像方式,如图。

  1. Cache容量多大? 16KB
    2^(s+w)=1M=2^20
    s+w=20
    2^s=512
    s=9
    w=20-9=11
    2^w*8=2^14=16k
  2. Cache的页内地址有多少位? 11位
    w=11
  3. Cache的标记有多少位? 9位
    s=9

第四章

  • RISC和CISC的区别
    CISC:复杂指令系统计算机
    RISC:精简指令系统计算机
    CISC比RISC指令系统庞大
  • 为什么不同指令执行不同?
    OP字段(操作码)不同。不同的op对应不同的指令

    第四章拓展知识

    |比较|RISC|CISC|
    |-|-|-|
    |名称|精简指令系统计算机|复杂指令系统计算机|
    |时钟周期|通常1个|更多|
    |控制|硬布线逻辑|微程序控制|
    |指令种类|少|多|
    |寻指方式|少|多|

两者都可以采用流水线技术,RISC更适合而已。


第五章

  • CPU的功能(p145)
    • 指令控制
    • 操作控制
    • 时间控制
    • 数据加工
  • 同步/异步控制方式
    • 各项操作采用/不采用统一的时钟信号控制
  • PC为什么加1?
    为下一条指令做准备。
  • 方框图中,为什么第一个方框能共用,后面的不行?
    第一个方框是取指周期。
  • 一个方框代表一个CPU周期
  • 为什么取完指令后会有一个菱形框
    判定测试,做的是指令译码,根据OP字段不同分析测试
  • 微指令:在机器的一个CPU周期中,一组实现一定操作功能的微命令的组合
  • 微程序:一条机器指令的功能是用许多条微指令组成的序列来实现的
  • 为什么软件可以控制硬件?
    指令的OP字段不一样。
  • 为什么机器指令码的OP字段不一样?
    地址转移后,强制置1的位置不一样,后面的分支和跳转不一样
  • 机器指令和微程序的关系
    • 一条机器指令对应的一个微程序,这个微程序由若干条微指令序列组成的
    • 指令存放在存储器中;微指令存放在控制器中
    • 一个CPU周期对应一条微指令,一个指令周期至少包含两个CPU周期(取指令,执行)
  • RISC的全称和特点
    • 全称:精简指令系统计算机
    • 一个有限的简单的指令系统
    • CPU配备大量的通用寄存器
    • 强调对指令流水线的优化

第五章拓展知识

  • 同步/异步传输
    • 同步传输:CPU↔内存储器、CPU↔PCI、CPU↔I/O
    • 异步传输:I/O↔打印设备(基于缓存池)

第六章

  • 总线分类(p189)
    • 内部总线:CPU内部连接各寄存器及运算部件之间的总线,称为内部总线
    • 系统总线:CPU同计算机系统的其他高速功能部件,如存储器、通道等互相连接的总线
    • I/O总线:中、低速I/O设备之间相互连接的总线
  • 总线带宽=总线位宽×总线工作频率
    • 总线带宽:单位时间内总线上可传送的数据量
    • 总线位宽:总线上能同时传送的数据位数。1/8/16/32位
    • 总线工作频率:用于控制总线操作周期的时钟信号的频率
  • 单总线结构特点:简单,易于扩充
  • 双总线结构:ppt7
  • 直接存储器DMA(Direct Memory Access)
    如果由外围设备指定的地址对应于一个主存单元,则主存予以响应,于是在主存和外设之间将进行直接存储器传送
  • 简单总线结构的不足之处
    • CPU是总线上唯一的主控者
    • 总线结构紧密与CPU相关,通用性较差
  • 信息传送方式(p195)
    • 串行传送
    • 并行传送
    • 分时传送
  • 总线仲裁部件:以某种方式选择其中一个主设备作为总线的下一个主方(p198)
  • 集中式仲裁:每个功能模块都有两条线连到总线控制器
    • 总线请求信号线BR:送往仲裁器
    • 总线授权信号线BG:仲裁器送出
  • 在查询链中,离总线仲裁器最近的设备具有最高优先级
  • 分布式仲裁:不需要集中的总线仲裁器
  • 同步总线必须按最慢的模块来设计时钟

Not just for exam. 后期不断补充新的知识。

第一章

OSI/RM参考模型

🚧施工中🚧

  • 物理层:利用传输介质为数据链路层提供物理连接,负责处理数据传输并监控数据出错率,以便数据流的透明传输
  • 数据链路层:在物理层提供的服务基础上,在通信的实体间建立数据链路连接,传输以“帧”为单位的数据包,并采用差错控制与流量控制方法,使有差错的物理线路变成无差错的数据链路
  • 网络层:为数据在节点之间传输创建逻辑链路,通过路由选择算法为分组通过通信子网选择最适当的路径,以及实现拥塞控制、网络互联等功能
  • 应用层:为应用软件提供了很多服务,实现具体的应用功能

网络协议

网络协议是为进行网络中的数据交换而建立的规则、标准或约定。由语法、语义和时序(或顺序或同步)三个要素组成。
语法,即数据与控制信息的结构或格式。
语义,即需要发出何种控制信息,完成何种动作以及做出何种响应。
时序,即事件实现顺序的详细说明。

各种协议

首部

首部(尾部) 长度(Byte)
以太网MAC帧首部和尾部 18
网络层IP首部 20(Max:60)
运输层UDP首部 8
运输层TCP首部 20(Max:60)

中间设备

将网络互相连接起来要使用一些中间设备

层次 中间设备
网络层以上 网关
网络层 路由器
数据链路层 网桥(桥接器)、交换机
物理层 转发器

数据传送单元

层次 单元
应用层 报文
运输层 报文段
TCP:报文段
UDP:用户数据报
网络层 包、分组
TCP/IP:IP数据报
数据链路层
物理层 比特流

第二章 物理层

信道的极限容量

奈奎斯特准则

在理想低通(没有噪声、带宽受限)信道中

:理想信通状态下的极限数据传输速率(bit/s或b/s或bps)
:信道的频率带宽(Hz)
:极限码原传输速率
:每个码元的离散电平数目(指有多少种不同的码元)

香农公式

:信道的的极限数据传输速率(bit/s或b/s或bps)
:信道的频率带宽(Hz)
:信道内所传信号的平均功率
:信道内部的高斯信号功率

物理层4个特性

  • 机械特性
  • 电气特性
  • 功能特性
  • 过程特性

信道复用技术

(p56)

  • 频分复用(FDM)
  • 时分复用(TDM)
    • 统计时分复用(STDM)
  • 波分复用(WDM)
  • 码分复用(CDM)

调制技术

  • 调频FM
  • 调幅AM
  • 调相PM


第三章 数据链路层

数据链路层的主要问题

封装成帧
透明传输
差错检测

网络拓补结构

局域网可按网络拓补分类(p84)

星形网(最广泛)
环形网
总线网
(网状)

数据链路层的两个子层

逻辑链路控制LLC
媒体接入控制MAC

CSMA/CD协议

载波监听多路访问/冲突检测协议(p87)
适用于总线形网络或半双工网络环境
CSMA/CD=多点载入+载波监听+碰撞检测

碰撞检测

电磁波在1km电缆的传播时延越为5μs
:单程端到端的传播时延
最迟要经过的时间才能知道自己发的数据和其他站发的是否发生碰撞
帧间最小间隔:9.6μs=96比特时间

100BASE-T以太网

在双绞线上传输(p106)

CSMA/CA协议

802.11标准定义了广泛适用于无线局域网的CSMA/CA协议,把冲突检测改为冲突避免


第四章 网络层

Ip地址和Mac地址的区别

从层次的角度看,物理地址是数据链路层和物理层使用的地址。而IP地址是网络层及其以上各层使用的地址,是一种逻辑地址。

由于全世界存在各式各样的网络,使用不同的硬件地址。要使这些异构网络能够互相通信,就必须进行非常复杂的硬件地址转换工作。由用户或用户主机来完成这项工作几乎是不可能的事。但统一的IP地址把这个复杂问题解决了。连接到Internet的主机只需拥有统一的IP地址,它们之间的通信就像连接在同一个网络上那样简单方便。当需要把IP地址转换为物理地址时,使用ARP协议即可实现。

区别 IP地址 MAC地址
所在层 网络层 数据链路层
地址 逻辑地址 硬件地址
分配方式 基于网络拓补结构,通过手动或字典跟配,可以更改 基于制造商,与硬件绑定,全球唯一,一般不能更改
长度 4字节 6字节
寻址协议
地址使用 Internet协议 Erhernet协议

三种路由协议

协议 RIP OSPF BGP
中文 路由信息协议 开放最短路径优先协议 边界网关协议
路由算法 距离向量 链路状态 路径向量
算法基础 Bellman-Ford Dijkstra
类型 内部网关协议IGP 外部网关协议EGP
层次 应用层 网络层 应用层
传递协议 UDP IP TCP
路径选择 跳数最少 代价最低 较好,非最佳
交换结点 和本结点相邻的路由器 网络中的所有路由器 和本结点相邻的路由器
交换内容 当前本路由器知道全部信息,自己的路由表 与本路由器相邻的所有路由器的链路状态 首次 整个路由表
非首次 有变化的部分

IP的私有地址

私有地址分3类:
A类: 第一段为10的都是私有地址
10.0.0.1 ~ 10.255.255.254
10.0.0.0表示整个网段,10.255.255.255是广播地址
B类: 以172.16 ~ 172.31开头的都是私有地址
172.16.0.1 ~ 172.31.255.254
172.16.0.0表示整个网段,172.31.255.255是广播地址
C类: 以192.168开头的都是私有地址
192.168.0.1 ~ 192.168.255.254
192.168.0.0表示整个网段,192.168.255.255是广播地址

单播和多播

在一对多通信中:
单播:点对点
多播:一点对多点
任播:终点是一组计算机,但数据报只交付其中一台,通常距离最近

常见网络命令

ping(p148)
tracert(p148)
nslookup
netstat
route
ipconfig


第五章 运输层

udp和tcp

TCP/IP运输层的两个主要协议

  1. 用户数据报协议UDP
  2. 传输控制协议TCP

udp和tcp的特点

特点 UDP TCP
主要特点 简单方便,但不可靠
连接 无连接 面向连接的运输层协议
可靠交付? 尽最大努力交付,
不保证可靠交付
所有维护可靠性的工作由用户在应用层完成
可靠交付
无差错,不丢失,不重复,按序到达
方向 支持一对一,一对多,多对一,多对多的交互通信 每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的
全双工通信
面向 报文 字节流(流入到进程或从进程流出的字节序列)
首部 开销小 开销大
拥塞控制 没有

虽然TCP面向字节流,但是采用的是对报文段的确认机制。

udp和tcp伪首部的作用

计算检验和。
把首部和数据部分一起检验。
udp的伪首部,协议号为17
tcp的伪首部,协议号为6

udp和tcp的首部

tcp可靠传输的工作原理

信道利用率


其中,
为信道利用率
为分组长度/数据率
为接收方发送确认分组需要的时间
为往返时间

停止等待协议

优点:简单
缺点:信道利用率太低

连续ARQ协议和滑动窗口协议

超时重传时间选择

第一次测量:

后面:

其中,
为报文段的往返时间
为加权平均往返时间(平滑的往返时间)
为超时重传时间
的偏差的加权平均值

推荐

Karn算法:在计算加权平均时,只要报文段重传了,就不采用其往返时间样本。这样得出的加权平均就比较准确

tcp的流量控制

利用滑动窗口进行流量控制。
发送方的发送窗口不能超过接收方给出的接收窗口的数值。
TCP的窗口单位是字节,不是报文段。

tcp的拥塞控制

拥塞:

拥塞控制:防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不至于过载。

拥塞控制算法(p241)

MSS:最大报文段长度
cwnd:拥塞窗口
rwnd:接收方窗口(通知窗口)
ssthresh:慢开始门限
发送窗口的上限值=Min[rwnd,cwnd]

超时时,执行慢开始拥塞避免
3-ACK时,执行快重传快恢复

具体如下:

1.慢开始

由小到大逐渐增大注入到网络中的数据字节,由小到大逐渐增大拥塞窗口数值

tcp开始发送报文段时,先设置cwnd=1~2个MSS(目的:试探一下网络的拥塞情况),然后再逐渐增大cwnd。
发送方每收到一个对新报文的确认(不包括对重传的确认),就把发送方的拥塞窗口+1。即cwnd加倍

当发送方判断网络拥塞(未按时收到确认)时

  • 第一步:

  • 第二步:重新执行慢开始算法
    目的:迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完。

2.拥塞避免

加法增大AI
拥塞窗口cwnd按线性规律缓慢增长,每经过一个往返时延RTT就把cwnd加1,而不是加倍。

目的:让拥塞窗口cwnd缓慢增大。

慢开始门限ssthresh的用法:

算法
cwnd < ssthresh 慢开始
cwnd = ssthresh 拥塞避免
cwnd > ssthresh 慢开始或拥塞避免

当发送方判断网络拥塞(未按时收到确认)时

  • 第一步:

  • 第二步:重新执行慢开始算法
    目的:迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完。

慢开始和拥塞避免遇到网络拥塞,都要这么做。

3.快重传

发送方只要一连收到3个重复确认(3个冗余ACK),就可知道现在并未出现网络拥塞,而是接收方少收到一个报文段,因而立即重传相应的报文段,而不等待报文段的超时计时器再重传。
目的:让发送方尽早知道发生了个别报文段的丢失

4.快恢复

乘法减小MD
发送方连续收到3个冗余ACK时,

然后执行拥塞避免算法(加法增大)

与慢开始算法不同的是,它不是将cwnd调整为1,而是减为一半。要预防网络发生拥塞,但发送方认为没有那么严重的拥塞。


tcp的有限状态机

alt text


第五章习题

课本p253

5-12

一个应用程序用 UDP, 到了IP层把数据报再划分为4个数据报片发送出去。结果前两个数据报片丢失,后两个到达目的站。过了一段时间应用程序重传UDP,而IP层仍然划分为4个数据报片来传送。结果这次前两个到达目的站而后两个丢失。试问:在目的站能否将这两次传输的4个数据报片组装为完整的数据报?假定目的站第一次收到的后两个数据报片仍然保存在目的站的缓存中。

解答:不行。重传时, IP数据报的标识字段会有另一个标识符。仅当标识符相同时IP数据报片才能组装成一个IP数据报。前两个IP数据报片的标识符与后两个IP数据报片的标识符不同,因此不能组装成一个IP数据报。

5-21

假定使用连续 ARQ 协议,发送窗口大小是3, 而序号范围是[0, 15],而传输媒体保证在接收方能够按序收到分组。在某一时刻,在接收方,下一个期望收到的序号是5。试问:

(1) 在发送方的发送窗口中可能出现的序号组合有哪些?
(2) 接收方已经发送出的、但仍滞留在网络中(即还未到达发送方)的确认分组可能有哪些?说明这些确认分组是用来确认哪些序号的分组。

解答:

(1) 在接收方,下一个期望收到的序号是5。这表明序号到4为止的分组都已收到。若这些确认都已到达发送方,则发送窗口最靠前,其范围是[5,7]。
假定所有的确认都丢失了,发送方都没有收到这些确认。这时,发送窗口最靠后,应为[2, 4] 。因此,发送窗口可以是[2, 4], [3, 5], [4, 6], [5, 7]中的任何一个。

(2) 接收方期望收到序号5 的分组,说明序号为2,3,4的分组都已收到,并且发送了确认。
对序号为 1 的分组的确认肯定被发送方收到了,否则发送方不可能发送4号分组。可见,对序号为2,3,4的分组的确认有可能仍滞留在网络中。这些确认是用来确认序号为2,3,4的分组的。

5-68

在 TCP 的连接建立的三报文握手过程中,为什么第三个报文段不需要对方的确认?这会不会出现问题?

A在发送第三个报文段时有两种选择

  • 仅仅是确认而不携带数据
  • 不仅是确认,而且携带上自己的数据

当服务器端B在经过一段时间后未收到来自A的确认报文段,会终止这个半开状态,A必须重新建立TCP连接。这是第三个报文段的丢失导致TCP连接无法建立。
但假设A紧接着就发送数据,由于在数据报文段中,自己的序号不变,ACK=1,确认号是B的初始序号加1。当B收到这个报文段,就知道A收到了自己发送的SYN+ACK报文段,于是进入ESTABLISH状态。
A丢失了第三个报文段就不会造成影响。于是A发送第一种选择,只要紧接着发送数据报文段就无妨。

udp和tcp选择题

  • tcp首部没有目标主机ip地址
  • udp提供不可靠的传输服务,不需要对报文编号,所以不会有序列号字段。而tcp提供可靠的传输服务,因此需要设置序列号字段。
  • 目的IP地址属于ip数据报中的内容。


第六章 应用层

http的一次请求过程

  1. 在浏览器输入URL,并按下回车键。
  2. 浏览器向DNS服务器发出域名解析请求并获得结果。
  3. 根据目的IP地址和端口号,与服务器建立TCP连接。
  4. 浏览器向服务器发送数据请求
  5. 服务器将网页数据发送给浏览器
  6. 通信完成,断开TCP连接
  7. 浏览器解析收到的数据并显示

域名系统DNS

(p261)

电子邮件

(p296)

SMTP POP3 IMAP MIME
中文 简单邮件传输协议 邮局协议 网际报文存取协议 通用互联网邮件扩充
功能 发件人的用户代理向邮件服务器发送邮件,以及发送方邮件服务器向接收方邮件服务器发送邮件 用户代理从接收方邮件服务器上读取邮件 增加邮件主体的结构

pop3和IMAP

区别 POP3 IMAP
复杂度 简单 复杂
特点 脱机协议,所有对邮件的处理者都在用户的PC机上进行 联机协议,用户可以操纵ISP的邮件服务器的邮箱
从服务器读取邮件后就删除这个文件 在用户发出删除命令之前一直保存邮件
功能 收件箱 仅在客户端内 客户端与邮箱更新同步
发件箱
创建文件夹
草稿
垃圾文件夹 不支持 支持
广告邮件

MIME

SMTP的缺点

  1. 不能传送执行文件或其它的二进制对象
  2. 限于传送7为的ASCII码
  3. 拒绝超过一定长度的邮件
  4. 有的没有完全按照SMTP的互联网标准
    • 回车换行
    • 超过76字符的处理
    • 多余空格的删除
    • tab转换为若干个空格

因为SMTP存在一些缺点和不足,所以通过MIME并非改变或取代SMTP.MIME继续使用RFC822格式,但增加了邮件主体的结构,并定义了传送非ASCII码的编码规则.也就是说,MIME邮件可在已有的电子邮件和协议下传送.

包括:

  1. 5个新的邮件首部字段
  2. 邮件内容的格式
  3. 传送编码

DHCP

(p304)
动态主机配置协议
即插即用连网


第七章 网络安全

信息安全

机密性:不暴露给未授权的实体或进程
完整性:只有得到允许的人才能修改数据,能判别出数据是否已被篡改。未经授权不可改变!
可用性:得到授权的的实体在需要时可访问数据,攻击者不能占用所有的资源而阻碍授权者的工作
可控性:可以控制授权范围内的信息流向及行为方式
可审查性:对出现的信息安全问题提供调查的依据和手段

安全性威胁

(p334)

  • 被动攻击
    • 截获
    • 流量分析
  • 主动攻击
    • 篡改
    • 恶意程序
    • 拒绝服务DOS

计算机病毒

引导区病毒:破坏引导盘、文件目录等
宏病毒:破坏OFFICE文件相关
木马病毒:控制操作
蠕虫病毒:自我复制,网络传播,消耗大量带宽,破坏文件,窃取敏感信息,并安装后门程序

安全

  • 机密性
  • 端点识别
  • 信息的完整性
  • 运行的安全性

密码体制

数据加密模型

明文
密文
密钥
加密算法
解密密钥
解密算法

两类密码体制

(p338)

对称密钥体制:加密密钥与解密密钥都是用相同密钥的密码体制

非对称密钥体制/公钥密码体制:使用不同的加密密钥与解密密钥

公钥加密,私钥解密

常见的对称加密算法:aes、des、md5等
常见的非对称加密算法有rsa、dsa、ecc等

数字证书、数字签名

用户A和B要进行安全通信,使用数字证书来对用户的身份进行认证;使用数字签名确保消息不可否认

第九章 无线网络和移动网络

wifi从一代到七代,分别是802.11 b/a/g/n/ac/ax/be

DIFS, SIFS, CSMA/CA, DCF, PCF, SSID

DIFS (Distributed Inter-Frame Space)

  • 定义:分布式帧间间隔,是IEEE 802.11无线局域网标准中定义的一种帧间间隔时间.
  • 作用:用于在无线网络中管理信道访问,防止数据包碰撞.
  • 特点
    • 当一个节点检测到信道空闲时,它会等待DIFS时间,然后尝试发送数据.
    • 如果检测到信道忙,则等待信道空闲后再等待DIFS时间.
    • DIFS是CSMA/CA协议的一部分,用于减少数据包碰撞的概率.

SIFS (Short Inter-Frame Space)

  • 定义:短帧间间隔,是比DIFS更短的帧间间隔时间.
  • 作用:用于高优先级的传输,如确认帧、数据帧的快速响应等.
  • 特点
    • SIFS比DIFS短,因此具有更高的优先级.
    • 在CSMA/CA协议中,SIFS用于快速响应,以减少传输延迟.

CSMA/CA (Carrier Sense Multiple Access with Collision Avoidance)

  • 定义:带有冲突避免的载波侦听多路访问.
  • 作用:无线局域网中的信道访问控制机制.
  • 特点
    • 载波侦听:节点在发送数据前先侦听信道是否空闲.
    • 冲突避免:通过使用DIFS和SIFS等帧间间隔来减少数据包碰撞.
    • 二进制指数退避算法:如果发生碰撞,节点会等待一个随机时间后重试发送,以进一步降低碰撞概率.

DCF (Distributed Coordination Function)

  • 定义:分布式协调功能.
  • 作用:IEEE 802.11标准中定义的一种信道访问机制,基于CSMA/CA协议.
  • 特点
    • 适用于无中心节点的无线网络,如对等网络.
    • 使用DIFS和SIFS等帧间间隔来管理信道访问.
    • 提供基本的信道访问控制,但不支持QoS(服务质量).

PCF (Point Coordination Function)

  • 定义:点协调功能.
  • 作用:IEEE 802.11标准中定义的另一种信道访问机制,由中心节点(如AP)控制.
  • 特点
    • 适用于有中心节点的无线网络,如基础设施网络.
    • 中心节点负责调度和管理信道访问.
    • 支持QoS,可以为不同优先级的数据提供不同的服务.

SSID (Service Set Identifier)

  • 定义:服务集标识符.
  • 作用:用于标识无线网络的名称.
  • 特点
    • 用户可以通过输入正确的SSID来连接到特定的无线网络.
    • SSID可以隐藏,以增加网络的安全性.
    • SSID是区分不同无线网络的重要标识.


计科期末考试出题

  1. 读程序题
  2. 程序填空题
  3. 写程序题:计算
  4. 写程序题:循环分支
  5. 写程序题:中断

第3章 80x86的指令系统和寻址方式

80x86的寻址方式


80x86的指令系统

数据传送指令(p47)

通用数据传送指令

mov
  1. mov mem/reg1,mem/reg2
    先略。。。直接看书
push进栈指令
1
push src

(sp) ← (sp)-2
((sp)+1,(sp)) ← (src)

格式

push reg
push mem
push data8086不行
push segreg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
push ax      ; 推送 AX 寄存器
push bx ; 推送 BX 寄存器
push cx ; 推送 CX 寄存器
push dx ; 推送 DX 寄存器
push sp ; 推送 SP 寄存器
push bp ; 推送 BP 寄存器
push si ; 推送 SI 寄存器
push di ; 推送 DI 寄存器

push word ptr [address] ; 推送内存地址中的值

push cs ; 推送 CS 段寄存器
push ds ; 推送 DS 段寄存器
push es ; 推送 ES 段寄存器
push ss ; 推送 SS 段寄存器
pop出栈指令

注意要画栈图

1
pop dst

(dst) ← ((sp)+1,(sp))
(sp) ← (sp)+2

pop reg
pop mem
pop data8086不行
pop segreg

累加器专用传送指令

这些指令不影响标志位

in
1
2
3
4
in al,port ;字节, (al) ← (port)
in ax,port ;字, (ax) ← (port+1,port)
in al,dx ;字节, (al) ← ((dx))
in ax,dx ;字, (ax) ← ((dx)+1,(dx))
out
1
2
3
4
out port,al ;字节, port ← (al)
out port,ax ;字, (port+1,port) ← (ax)
out dx,al ;字节, ((dx)) ← (al)
out dx,ax ;字, ((dx)+1,(dx)) ← (ax)
xlat换码指令

al=[bx+al]

地址传送指令

lea有效地址送寄存器
1
lea reg,sec ;(reg)<-src

异同:lea bx,listmov bx,offset list, mov更快

lds, les, lfs, lgs, lss指针送寄存器和?s

p56, 实验暂时不用

标志寄存器传送指令

p57, 实验暂时不用

类型转换指令

cbw

将al的内容符号扩展到ah,形成ax的字。
若(AL)的最高有效位为0,则(AH)= 00H
若(AL)的最高有效位为1,则(AH)= 0FFH

cwd/cwde

将ax的内容符号扩展到dx,形成dx:ax中的双字。
若(AX)的最高有效位为0,则(DX) = 0000H
若(AX)的最高有效位为1,则(DX) = 0FFFFH


算术指令

加法指令

add加法
adc带进位加法
inc 加1指令

减法指令

sub减法
sbb带借位减法
dec减1
neg求补

按位求反+1

cmp比较

前操作数-后操作数,但是不保存结果,只设置条件标志位

乘法指令

目的操作数必须是累加器

mul无符号数乘法
1
mul src

(ax)<-(al)(src) ;字节操作数
(dx,ax)<-(ax)
(src) ;字操作数

imul带符号数乘法

同上,但是是带符号数

除法指令

div无符号数除法

div src

字节操作:
(ax)/(src)=(al)……(ah)
字操作:
(dx,ax)/(src)=(ax)……(dx)
注意进制转换的代码

idiv带符号数除法

同上

十进制调整指令

有压缩的BCD码调整指令:
DAA 加法的十进制调整指令
DAS 减法的十进制调整指令

非压缩的BCD码调整指令:
AAA 加法的ASCII调整指令
AAS 减法的ASCII调整指令
AAM 乘法的ASCII调整指令
AAD 除法的ASCII调整指令

逻辑指令

逻辑运算指令

and 逻辑与指令
or 逻辑或指令
not 逻辑非指令
xor 异或指令

要使操作数的某些位变反,使用xor,那些位设为1

test 测试指令

做and运算,但是不保存结果,只置条件码
要测试操作数的某位是都为1,可以先将操作数取反,再用test测试。

移位指令(p73)

e.g. shl opr,cnt
在8086中,cnt可以是cl或者1

shl 逻辑左移指令

无符号数乘法

sal 算数左移指令

有符号数乘法

shr 逻辑右移指令

无符号数除法

sal 算数右移指令

有符号数除法

rol 循环左移指令
ror 循环右移指令
rcl 带进位循环左移指令
rcr 带进位循环右移指令

串处理指令

这里要写一下字符串代码

与rep相配合工作的movs, stos, lods, ins, outs

rep重复串操作

重复串操作直到计数器Count Reg的内容为0位为止
操作:

1
2
3
while Count_Reg != 0:
Count_Reg-=1
执行后面的串指令
movs 串传送指令

格式

1
2
3
movs dst,src
movsb ;字节
movsw ;字

第一种格式要在操作数里标名是字还是字节操作。
movs es:byte ptr[di],ds:[si]

相当于strcpy
movs可以把由源变址寄存器指向的数据段中的一个字(或字节),传到目的变址寄存器指向的附加段中的一个字(或字节)去,同时根据方向标志以及数据格式(字or字节),对源变址寄存器和目的变址寄存器进行修改。

执行操作:

  1. ((DI)) ← ((SI))
  2. 字节操作:(SI)←(SI)±1, (DI)←(DI)±1
    字操作: (SI)←(SI)±2, (DI)←(DI)±2
    方向标志DF=0时用 +,DF=1时用 - 。

执行REP MOVS之前,应先做好:

  1. 源串首地址(末地址)→ SI
  2. 目的串首地址(末地址)→ DI
  3. 串长度 → CX
  4. 建立方向标志(CLD使DF=0,STD使DF=1)

方向标志

  • cld: df=0, 地址自动增量
  • std: df=1, 地址自动减量
stos 存入串指令

格式

1
2
3
stos dst
stosb ;字节
stosw ;字

相当于memset
将al、ax的内容存入由目的变址寄存器指向的附加段的某单元中,并根据……
初始化某一个缓冲区时很有用

执行操作:

  1. 字节操作:((DI))←(AL), (DI)←(DI)±1
  2. 字操作:((DI))←(AX), (DI)←(DI)±2

例:把附加段中的5个字节缓冲区置为20H

1
2
3
4
5
lea  di, mess2
mov al, 20H
mov cx, 5
cld
rep stosb

lods 从串取指令

格式

1
2
3
lods src
lodsb ;字节
lodsw ;字

LODS指令一般不与REP联用
源串必须在数据段中,目的串必须在附加段中,
但源串允许使用段跨越前缀来修改。
不影响条件标志位

执行操作:
字节操作:(AL)←((SI)),(SI)←(SI)±1
字操作:(AX)←((SI)),(SI)←(SI)±2

ins 串输入

格式

1
2
3
ins dst,dx
insb ;字节
insw ;字

执行操作:
字节操作:(DI)←((DX)), (DI)←(DI)±1
字操作:(DI+1,DI)←((DX)), (DI)←(DI)±2

outs 串输出

格式

1
2
3
outs dx,src
outsb ;字节
outsw ;字

执行操作:
字节操作:((DX)) ← (SI), (SI)←(SI)±1
字操作:((DX)) ←(SI+1,SI), (SI)←(SI)±2

repe/repz,repne/repnz,cmps,scas

repe/repz 为相等/为零时重复串操作
1
2
3
while Count_Reg!=0 and zf!=0:
Count_Reg-=1
执行其后的串指令
repne/repnz 为不相等/不为零时重复串操作
1
2
3
while Count_Reg!=0 and zf!=1:
Count_Reg-=1
执行其后的串指令
cmps 串比较指令

格式

1
2
3
cmps src,dst
cmpsb ;字节
cmpsw ;字

相当于strcmp

执行操作:
(1) ((SI)) - ((DI))
根据比较结果设置条件标志位:相等 ZF=1
(2) 字节操作:(SI)←(SI)±1, (DI)←(DI)±1
字操作:(SI)←(SI)±2, (DI)←(DI)±2

scas串扫描指令

格式

1
2
3
scas dst
scasb ;字节
scasw ;字

执行操作:
字节操作:(AL) - ((DI)), (DI)←(DI)±1
字操作:(AX) - ((DI)), (DI)←(DI)±2

控制转移指令

后面再看

无条件转移指令

jmp

条件转移指令(p89)

jz/je
jnz
js
jns
jo
jno
jp/jpe
jnp/jpo
jb/jnae
jnb/jae/jnc

循环指令

loop

Count_Reg!=0

loopz/loope

Count_Reg!=0 && zf=1

loopnz/loopne

Count_Reg!=0 && zf=0

子程序

call
ret

第8章 输入输出程序设计

(面向考试复习)

程序直接控制I/O方式(p283)

I/O指令(p284)

in和out

in 完成I/O -> CPU的信息传送
out完成CPU -> I/O的信息传送

0~0ffh,即0~255端口可以这样写:

1
2
3
4
5
6
;port是端口地址,一个8位的立即数
in al,port ;(al)<-(port)
in ax,port ;(ax)<-(port+1,port)

out port,al ;(port)<-(al)
out port,ax ;(port+1,port)<-(ax)

0~0ffffh,即0~255端口可以这样写(当端口>0ffh时,必须这样写!)

1
2
3
4
5
6
;dx里存了端口地址
in al,dx ;(al)<-((dx))
in ax,dx ;(ax)<-((dx)+1,(dx))

out dx,al ;((dx))<-(al)
out dx,ax ;((dx)+1,(dx))<-(ax)

注意端口是否带“h”,例如126h是大于十进制的255的,就得用dx

用法示例

  1. 把一个字,从端口地址28和29,传到存储器的字单元data_word中

    1
    2
    in  ax,28h
    mov data_word,ax
  2. 检测端口地址27h的第2位是否为1,如果1就是转到错误处理
    注意这里的第几位是从右到左从0数起
    因为test就是只改变flags的and,所以用来查1

    1
    2
    3
    in   al,27h
    test al,00000100b
    jnz error
  3. 将端口地址为126h的命令寄存器,第7位置1

    1
    2
    3
    4
    mov dx,126h
    in al,dx
    or al,80h ;80h=10000000b
    out dx,al

中断传送方式

8086的中断分类(p290)

中断标志位if

设置中断允许位(if=1)sti set interupt flag
清除中断允许位(if=0)cli clear interupt flag

中断屏蔽寄存器(端口21h)

7 6 5 4 3 2 1 0
打印机 软盘 硬盘 串行通信口1 串行通信口2 保留 键盘 定时器

中断屏蔽寄存器(端口20h)

7 6 5 4 3 2 1 0
R SL EOI 0 0 L2 L1 L0

扩充(实验书p92):

键盘的输入寄存器(PA,端口60h)

PB位7 7 6 5 4 3 2 1 0
PB7=1 磁盘驱动器数 显示器类型 系统板上RAM数 未用 非磁盘系统
PB7=0 键盘扫描码

控制寄存器(PB,端口61h)

7 PA选源,1=键盘应答
6 0=禁止键盘时钟
5 0=允许由扩充槽的错误信号
4 0=允许ram
3 0=启开盒式带马达
2 PC0~3选源
1 扬声器脉冲门
0 定时器2与门

1ch中断一秒钟约产生18次中断,具体使用可以看2324期末卷最后一题

中断向量表(p293)

功能 预置 执行 返回
设置中断向量 ah=25h
al=中断类型号
ds:dx=中断向量
int 21h
取中断向量 ah=35h
al=中断类型号
int 21h es:bx=中断向量

中断操作:

  1. 取中断类型号
  2. 计算中断向量地址
  3. 取中断向量,偏移地址送IP,段地址送CS
  4. 转入中断处理程序
  5. 中断返回到int的下一条指令

使用dos功能调用存取中断向量,模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
;保存原来的中断向量
mov al,n ;中断类型号
mov ah,35h ;取中断向量到es:bx
int 21h
push es
push bx
;设置新的中断向量
push ds
mov ax,seg myfunc
mov ds,ax
mov dx,offset myfunc
mov al,n
mov al,25h
int 21h
pop ds
;重新设置原来的中断向量
pop dx ;原来的bx
pop ds ;原来的es
mov al,n
mov ah,25h
int 21h
ret
;...
myfunc proc near
;...
iret
myfunc endp
;...

p300的程序可能会被改成考试题

p301响铃程序

只有铃响:

1
2
3
4
5
6
7
8
9
        mov    dx, 100h
in al, 61h
and al, 11111100b
sound: xor al, 2
out 61h, al
mov cx, 140h
wait1: loop wait1
dec dx
jne sound

完整程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
datarea segment
count dw 1
msg db 'The bell is ringing',0dh,0ah,'$'
datarea ends
prognam segment
main proc far
assume cs:prognam,ds:datarea,es:datarea
start:
push ds
sub ax,ax
push ax
mov ax,datarea
mov ds,ax
mov es,ax

;保存旧的中断向量
mov al,1ch ;1ch中断
mov ah,35h ;取中断向量,保存在es:bx里
int 21h
push bx
push es

;设置新的中断向量
push ds
mov dx,offset ring ;ring的偏移地址
mov ax,seg ring ;ring的段地址
mov ds,ax ;ds:dx=段地址:偏移地址
mov al,1ch ;1ch中断
mov ah,25h ;设置中断向量
int 21h
pop ds

;将21h端口的第0位清零,即打开定时器
in al,21h
and al,11111110b
out 21h,al
sti ;设置中断标志,允许中断。

;循环20000*30000次,因为次数太多一个寄存器装不下
mov di,20000
delay:
mov si,30000
delay1:
dec si
jnz delay1
dec di
jnz delay

;重新设置回旧的中断向量
pop dx
pop ds
mov al,1ch
mov ah,25h
int 21h
ret
main endp
ring proc near
push ds
push ax
push cx
push dx

mov ax,datarea
mov ds,ax
sti

dec count
jnz exit
;打印消息'The bell is ringing'
mov dx,offset msg
mov ah,09h
int 21h

mov dx,100 ;打开关闭的次数
in al,61h
and al,0fch ;61h端口的第0、1位清0,分别是定时器2和扬声器脉冲门
sound:
xor al,02 ;61h端口的第1位转置,扬声器脉冲门
out 61h,al

;等待,因为cpu比端口快的多
mov cx,1400h
wait1:
loop wait1

dec dx
jne sound
mov count,182 ;10s的铃响delay
exit:
cli
pop dx
pop cx
pop ax
pop ds
iret
ring endp
prognam ends
end start

堆栈情况

alt text
堆栈段(SS)没有变化,始终保持为 076B。
堆栈指针(SP)在每次执行PUSH指令后减少2,这是因为每次PUSH操作都会将一个寄存器的值(2 字节)压入堆栈。

  1. 一开始,sp初始化为0
  2. push ds后,sp=0000h-2=0fffeh,压入ds=075Ch
  3. sub ax,ax后,ax=0
  4. push ax后,sp=0fffeh-2=0fffch,压入ax=0

附录 DOS系统功能调用(常用)

AH 功能 调用参数 返回参数
00 程序终止 CS=程序段前缀PSP
01 键盘输入并回显 AL=输入字符
02 显示输出 DL=输出字符
09 显示字符串 DS:DX=串地址 字符串以’$’结尾
0A 键盘输入到缓冲区 DS:DX=缓冲区首址 (DS:DX)=缓冲区最大字符数 (DS:DX+1)=实际输入的字符数
25 设置中断向量 DS:DX=中断向量
AL=中断类型号
35 取中断向量 AL=中断类型号 ES:BX=中断向量

常用debug(实验书p186)

  • -d: 显示内存单元内容
  • -r: 寄存器和标志位状态
  • -g: 运行
  • -t: 单步运行
  • -u: 反汇编
  • -q: 退出
标志名 置位 复位
溢出Overflow 是OV 否NV
方向Direction 减量DN 增量UP
中断Interrupt 允许EI 屏蔽DI
符号Sign 负NG 正PL
零Zero 是ZR 否NZ
辅助进位Auxiliary Carry 是AC 否NA
奇偶Parity 偶PE 奇PO
进位Carry 是CY 否NC

实验代码

成绩排名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
datarea segment
grade dw 88,75,95,63,98,78,87,73,90,60
rank dw 10 dup(?)
datarea ends
prognam segment
main proc far
assume cs:prognam,ds:datarea,es:datarea
start:
push ds
sub ax,ax
push ax
mov ax,datarea
mov ds,ax
mov es,ax
call sort
call output
ret
main endp
sort proc
mov si,0
mov cx,10
outer_loop:
push cx
mov cx,10
mov dx,1
mov ax,grade[si]
mov di,offset grade
inner_loop:
cmp ax,[di]
jge no_add
inc dx
no_add:
add di,2
loop inner_loop
pop cx
mov rank[si],dx
add si,2
loop outer_loop
ret
sort endp
output proc
mov cx,10
mov si,0
t1:
push cx
mov ax,rank[si]
call print_dec
mov dl,' '
call putchar
pop cx
add si,2
loop t1
ret
output endp
putchar proc
mov ah,2
int 21h
ret
putchar endp
print_dec proc
;ax/?=al...ah, result:al,ah
mov bl,10
div bl
mov bx,ax
mov dl,bl
add dl,'0'
call putchar
mov dl,bh
add dl,'0'
call putchar
ret
print_dec endp
prognam ends
end start

ASCII码表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
datarea segment
datarea ends
prognam segment
main proc far
assume ds:datarea,cs:prognam,es:datarea
start:
push ds
sub ax,ax
push ax
mov ax,datarea
mov ds,ax
mov es,ax

mov dx,10h
mov bx,0
rotate:
mov ah,2
int 21h
inc bx
inc dx
push dx
cmp bx,16
mov dl,' '
mov ah,2
int 21h
jl continue
xor bx,bx
mov dl,0dh
mov ah,2
int 21h
mov dl,0ah
mov ah,2
int 21h
continue:
pop dx
cmp dx,100h
jl rotate
ret
main endp
prognam ends
end start

反转字符串

我流版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
datarea segment
limit db 30
len db ?
str db 30 dup('$')
datarea ends
prognam segment
main proc far
assume cs:prognam,ds:datarea,es:datarea
start:
push ds
sub ax,ax
push ax
mov ax,datarea
mov ds,ax
mov es,ax

;输入字符串
lea dx,limit
mov ah,0ah
int 21h
;回车换行
mov dl,0dh
mov ah,2
int 21h
mov dl,0ah
mov ah,2
int 21h
;di置为字符串长度减一,cx计数器置为字符串长度除以2
mov si,0
mov bl,len
xor bh,bh
mov di,bx
dec di
mov cx,1
;除以2
shr bx,cl
mov cx,bx
rotate:
mov al,str[si]
mov bl,str[di]
mov str[si],bl
mov str[di],al
inc si
dec di
loop rotate
lea dx,str
mov ah,9
int 21h
ret
main endp
prognam ends
end start

ppt递归版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
datarea segment
str db "123456",'$'
datarea ends
prognam segment
main proc far
assume cs:prognam,ds:datarea,es:datarea
start:
push ds
sub ax,ax
push ax
mov ax,datarea
mov ds,ax
mov es,ax

mov bx, offset str
push bx
call revers
pop bx
mov dl, [bx]
mov ah, 2
int 21h

ret
main endp
revers proc near
push bp
mov bp, sp
push ax
push bx
push dx
mov bx, [bp+4]
mov al, [bx]
cmp al, '$'
je return
re_call:
inc bx
push bx
call revers
pop bx
mov dl, [bx]
mov ah, 2
int 21h
return:
pop dx
pop bx
pop ax
pop bp
ret
revers endp

prognam ends
end start

查找子串位置,十进制、十六进制输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
datarea segment
sentence_label label byte
sentence_max db 50
sentence_len db ?
sentence db 50 dup('$')
key_label label byte
key_max db 30
key_len db ?
key db 30 dup('$')

cmd1 db 'Input a sentence:','$'
cmd2 db 'Input a keyword:','$'
no_match_str db 'No match!',0dh,0ah,'$'
match_str db "The location:",'$'
crlf_str db 0dh,0ah,'$'

datarea ends
prognam segment
main proc far
assume cs:prognam,ds:datarea,es:datarea
start:
push ds
sub ax,ax
push ax
mov ax,datarea
mov ds,ax
mov es,ax
loops:
lea dx,cmd1
call cout
call cin_sentence
call crlf
cmp sentence[0],3 ;比较ctrl+c
je exit
lea dx,cmd2
call cout
call cin_key
call crlf
call compare
jmp loops
exit:
ret
main endp
cin proc
mov ah,0ah
int 21h
ret
cin endp
cin_sentence proc
lea dx,sentence_label
call cin
ret
cin_sentence endp
cin_key proc
lea dx,key_label
call cin
ret
cin_key endp
cout proc
mov ah,09h
int 21h
ret
cout endp
crlf proc
lea dx,crlf_str
call cout
ret
crlf endp
compare proc
;cx=sentence_len-key_len+1
xor ch,ch
xor dh,dh
xor bx,bx
mov cl,sentence_len
mov dl,sentence_len
sub cx,dx
inc cx
rotate:
lea si,sentence[bx]
lea di,key
mov cl,key_len
xor ch,ch
cld
rep cmpsb
jz match
inc bx
loop rotate
no_match:
lea dx,no_match_str
call cout
ret
match:
lea dx,match_str
call cout
call print_dec
call crlf

lea dx,match_str
call cout
call print_hex
call crlf

ret
compare endp
;打印十进制数字
print_dec proc
;ax/?=al...ah
push bx
mov ax,bx
xor cx,cx
div10:
mov bl,10
div bl
push ax
inc cx
xor ah,ah
cmp al,0
jne div10
print10:
pop dx
mov dl,dh
add dl,30h
mov ah,2
int 21h
loop print10
pop bx
ret
print_dec endp
;打印十六进制数字
print_hex proc
push bx
xor ax,ax
div16:
mov dx,0fh
and dx,bx
push dx
inc ax
mov cl,4
shr bx,cl
cmp bx,0
jne div16
mov cx,ax
print16:
pop dx
add dx,'0'
cmp dx,'9'
jle not_letter
add dx,'A'-'0'-10
not_letter:
mov ah,2
int 21h
loop print16
pop bx
ret
print_hex endp
prognam ends
end start

之前Pyinstaller打包失败,所以换成cx-Freeze打包。

官网写的很清楚。
最简单粗暴的打包是这样的,可执行文件和pyinstaller一样生成在dist文件夹里

1
cxFreeze main.py

例如:

1
2
3
4
5
6
7
8
9
10
cxfreeze --script hello.py --target-dir dist

--script=要打包的主py文件
--init-script=开始启动的文件,如果没写绝对路径的话,会去cx_Freeze package的根目录里找
--base=NAME, --base-name=NAME
--target-name=生成可执行文件的名字,不要包含路径
--target-dir=生成可执行文件所在目录,默认为dist
--icon=图标
--shortcut-name=快捷方式的名字(MSI)
--shortcut-dir=MSI安装包

如果不想出现控制台窗口的话:就加上

1
--base-name="win32gui"

e.g.
1
cxfreeze --script main.py --target-dir dist --base-name="win32gui"

只打包了main.py,其它文件没有被打包上。copy到
每次都要敲命令行非常麻烦,新建一个bat文件批量复制,例如:

1
2
3
4
5
6
7
8
9
10
11
set "root_path=%~dp0"
cxFreeze --script main.py --icon=%root_path%Assets\icons\logo_orange.ico --target-dir dist --base-name="win32gui"
set exe_path=%root_path%dist
XCOPY %root_path%\Assets\ %exe_path%\Assets\ /E /I
XCOPY %root_path%\Temp\ %exe_path%\Temp\ /E /I
XCOPY %root_path%\Templates\ %exe_path%\Templates\ /E /I
XCOPY %root_path%\Views\ %exe_path%\Views\ /E /I
XCOPY %root_path%\Sqlite\ %exe_path%\Sqlite\ /E /I
XCOPY %root_path%\.venv\Lib\site-packages\sqlalchemy\ %exe_path%\lib\sqlalchemy\/E /I
echo END!
pause

原生pyqt


fluent

添加designer-fluent启动的外部工具

  • 学到了一个很好的脚本打开方式,新建一个这样的txt记事本文件,然后把后缀名改成.bat,最后放到外部工具里,
1
2
@echo off
start cmd /k "cd /【你放Fluent组件的盘符】 【你clone这个PyQt-Fluent-Widgets的文件夹】 && conda activate 【你的conda环境】 && python tools/designer.py"
  • 比如说,我的是这样的:
1
2
@echo off
start cmd /k "cd /d D:\GitHub\PyQt-Fluent-Widgets && conda activate D:\python\envs\qt5_env && python tools/designer.py"
  • 如果报错了,那么就一句一句复制贴贴到cmd里,看看哪里出问题。比如说,我们那时候,作者似乎不小心把tools文件夹给删了。。。这时候切换分支即可。
    例子:
1
2
3
4
/d
cd D:\GitHub\PyQt-Fluent-Widgets
conda activate D:\python\envs\qt5_env
python tools/designer.py
  • 没问题的话可以添加到pycharm里:
    文件/设置/工具/外部工具/+
    写上你工具的路径名,起个顺眼的名字。
    alt text
    当然你也可以用c/c++等语言写出来,编译,然后放exe文件。

实战问题大全和解决方法

在designer里设置的背景图片和icon在python里打开看不到

因为uic.loadUi 这个方法已经把背景图片和icon加载进去了
其实你可以换另一种方法,就是Designer里面不设置icon和背景图片,但在py里面设置
外部的图片 icon 资源不要在ui文件中引用 应在外部的py文件里写入。这么做有三个好处,一是分离资源,方便后续的管理,二是方便调试和自定义操作,三是可以减少ui文件的体积

解决未铺满问题

alt text
首先要用布局器进行布局 而不是frame
alt text
虽然frame一定程度上能对控件进行分类,但是效果不如布局器的好
尽量用Widget作为新建窗口 使用MainWindow的话,一是语义不符,二是有些臃肿

1
2
3
4
# 在每个窗体的py文件里面加上 这三行代码 保证布局的稳定
QApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)

聊天气泡框

csdn博客介绍
gitcode开源链接

pyinstaller和pipenv:py打包

踩坑记录:
首先用conda不知道为什么会出错。用了Virtualenv。
其次,它有一些import问题。
还是打包简单的项目文件比较好。后面我使用cx_Freeze配合bat后缀文件打包,解决了打包问题。可以看我的另一篇博客

年少不懂事,做mikumikudance时期,用记事本打开readme点md
我一般用vscode看,其实用jetbrain的软件也可以
vscode配这三个插件:alt text
完美。下载安装和学习这个就可以了
既然这就是个md文件,所以还要简单记录一下格式吗?
要的,我抄一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# 一级标题
## 二级标题
### 三级标题
#### 四级标题
##### 五级标题
###### 六级标题

---
上面是划线,如果划线上有字会变成二级标题。一堆=上面有字是一级标题。
各种分割线
***

* * *

*****

- - -

----------
*斜体文本*
_斜体文本_
**粗体文本**
__粗体文本__
***粗斜体文本***
___粗斜体文本___
~浅一点的字体~
~~删除线,非常爱用~~
==高光==

* 第一项
* 第二项
* 第三项

+ 第一项
+ 第二项
+ 第三项


- 第一项
- 第二项
- 第三项

1. 第一项
2. 第二项
3. 第三项

> 最外层
> > 第一层嵌套
> > > 第二层嵌套

还有现在在用的是区块。算了不抄了,直接看菜鸟教程吧。

git分支操作

git分支操作 可以当速查表看看

新建一个空白分支

1
git checkout --orphan newBranchName

签名认证

待填坑

git commit message标准

基本格式

type + 描述

type类型

  • feat 新功能
  • fix/to
    • fix 产生diff并自动修复问题。适合一次提交直接修复格式
    • to 只产生diff不自动修复此问题。适合于多次提交。最终修复问题提交时使用fix
  • docs 提交文档
  • style 格式 不影响代码运行的变动
  • refactor 重构
  • perf 优化
  • test 测试 单元测试
  • chore 构建过程或辅助工具的变动
  • revert 回滚到上一个版本
  • merge 代码合并
  • sync 同步主线或分支的bug

更新pip

1
python.exe -m pip install --upgrade pip

镜像源

  • 经常install时卡顿,一般会用清华大学镜像源
  • 单个安装使用镜像源
    1
    pip install 【要安装的库名】 -i https://pypi.tuna.tsinghua.edu.cn/simple
  • 永久设置镜像源
    1
    pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

    requirement.txt

  • 有一堆要安装的,要一个一个pip Install?
  • 不,把requirement.txtre放到一个文件夹里,cd到这个文件夹,然后
    1
    pip install -r requirements.txt
    导出分享给别人:
    1
    pip list --format=freeze > requirements.txt
0%