26. 1.
问题描述:
开始,我们来看一个简单的程序,“loop.s”。首先,阅读这个程序,看看你是否能理解它: cat loop.s。然后,用这些参数运行它:
./x86.py -p loop.s -t 1 -i 100 -R dx
这指定了一个单线程,每 100 条指令产生一个中断,并且追踪寄存器 %d。你能弄清楚 %dx 在运行过程中的值吗? 你有答案之后,运行上面的代码并使用 -c 标志来检查你的答案。注意答案的左边显示了右侧指令运行后寄存器的值(或内存的值)
解答:
使用cat命令查看loop.s文件(右边为添加的注释):
.main
.top // 标号
sub $1,%dx // dx寄存器值减1, 结果存入dx
test $0,%dx // 比较 dx寄存器的值与 0
jgte .top // 如果 dx 寄存器的值大于或等于 0,则跳转到标号 .top 处
halt // 结束线程
接着运行命令
./x86.py -p loop.s -t 1 -i 100 -R dx
-t 指定线程数为 1, -i 指定每个线程 100 条指令中断一次, -R 指定跟踪 dx 寄存器的值。可以添加-a dx=0参数初始化 dx 寄存器的值,不添加默认dx初始值为0。
运行结果:
由上面的汇编代码可得,dx初始为0,进行减1操作后为-1,接着再测试其是否为0,明显此时为-1不为0,因此不会跳转到top处而直接终止程序。
查看程序运行结果:
./x86.py -p loop.s -t 1 -i 100 -R dx -c
可以看到寄存器%dx一开始的值为0,后来变为了-1,线程停止。
26.2
问题描述:
现在运行相同的代码,但使用这些标志:
-/x86.py -p loop.s -t 2 -i 100 -a dx=3,dx=3 -R dx
这指定了两个线程,并将每个%dx 寄存器初始化为 3. %dx 会看到什么值?使用-c 标志运行以查看答案。多个线程的存在是否会影响计算?这段代码有竞态条件吗?
解答:
运行命令:
./x86.py -p loop.s -t 2 -i 100 -a dx=3,dx=3 -R dx
线程数为 2, 每个线程 100 条指令中断一次, 线程 0,1 的 dx 寄存器都初始化为 3,跟踪 dx 寄存器的值
运行结果:
运行命令查看答案:
./x86.py -p loop.s -t 2 -i 100 -R dx -a dx=3,dx=3 -c
运行结果:
线程 1 运行结果与线程 0 相同,dx的值最后都为-1。 多个线程不会影响计算,因为指令执行长度小于中断周期, 这段代码没有竞态条件
26.3
问题描述:
现在运行以下命令:
./x86.py -p loop.s -t 2 -i 3 -r -a dx=3,dx=3 -R dx
这使得中断间隔非常小且随机,使用不同的种子和-s 来查看不同的交替、中断频率是否会改变这个程序的行为?
解答:
分别运行命令:
./x86.py -p loop.s -t 2 -i 3 -r -a dx=3,dx=3 -R dx -c -s 0
./x86.py -p loop.s -t 2 -i 3 -r -a dx=3,dx=3 -R dx -c -s 1
./x86.py -p loop.s -t 2 -i 3 -r -a dx=3,dx=3 -R dx -c -s 2
来查看种子分别为0,1,2时的运行结果:
-
种子为0
-
种子为1
-
种子为2
可以看到,同样的中断频率,对于不同的seed,程序运行的顺序有所不同,所以中断频率是会影响程序的行为的,因为两个线程没有访问共享变量。但对于每个线程。它寄存器的值变化都是3->2->2->2->1->1->1->0->0->0->-1->-1->-1->-1,在本例中,中断频率没有影响程序的结果。
26.4
问题描述:
接下来我们将研究一个不同的程序(looping-race-nolock.s),该程序访问位于内存地址 2000 的共享变量,简单起见,我们称这个变量为 x.使用单线程运行它,并确保你了解它的功能,如下所示:
./x86.py -p looping-race-nolock.s -t 1 -M 2000
在整个运行过程中, x(即内存地址为 2000)的值是多少?使用-c 来检查你的答案。
解答
同第一题一样,先用cat命令查看looping-race-nolock.s文件
由代码可以知道程序的功能:
- 将内存地址2000中的值赋给寄存器%ax
- 将寄存器%ax中的值加1
- 将寄存器%ax中的值重新写回内存地址2000中
- 根据寄存%bx中的值执行以上循环(这里未设置,默认bx为0,执行一次)
由此得到程序单线程运行情况,由于地址2000和bx都未初始化,因此都默认为0。首先第一次循环地址2000的值加一后就终止循环,因此地址2000的值为1。
输入命令查看结果:
./x86.py -p looping-race-nolock.s -t 1 -M 2000 -c
可以看到,与分析的一致,地址2000的值最后为1。