我讲解这道题的目的是为了让大家理解结果为什么是那样的,假如对基础知识不是特别了解的人,可能会对答案有疑问,但是答案并没有详细讲解为什么会得到哪些答案。
这里推荐我写的另一篇博客,https://blog.csdn.net/ciqingloveless/article/details/84136002
,这里详细讲述了寄存器寻址,后面有的内存我回省略。
题目
假设下面的值存放在指定的内存地址和寄存器中:
地址 | 值 |
---|---|
0x100 | 0xFF |
0x108 | 0xAB |
0x100 | 0xFF |
0x100 | 0xFF |
寄存器 | 值 |
---|---|
%rax | 0x100 |
%rcx | 0x1 |
%rdx | 0x3 |
填写下表,给出下面之灵的效果,说明被更新的寄存器或内存位置,以及得到的值:
指令 | 目的 | 值 |
---|---|---|
addq %rcx,(%rax) | ||
subq %rdx,8(%rax) | ||
imulq $16,(%rax,%rdx,8) | ||
incq 16(%rax) | ||
decq %rcx | ||
subq %rdx,%rax |
解答
其实这道题的难点还是在寄存器寻址上,假如对寄存器寻址不是特别清楚,那么这道题可能特别绕,下面我就讲解答案。
根据二元运算符定义,使用add举例:
ADD S,D的含义是 D <- D + S
其他指令格式与上面相同,他的理解就是用D加上S放入D,这个放入D很关键。好了,下面进行答案讲解。
-
在addq %rcx,(%rax)这个题目中,我们列取一下各个的值:
S -> %rcx
D -> (%rax)
addq %rcx,(%rax) = (%rax) + %rcx
现在的问题是各个值是多少,那么这里着重说一下%rcx与(%rax)的区别,%rcx是寄存器寻址,(%rax)是寄存器间接寻址,%rcx就是所需要的值,(%rax)中的值是地址,所以(%rax)的值还得根据(%rax)中的值再去找一次,所以得出如下结果
S -> %rcx -> 0x1
D -> (%rax) -> 0x100 -> 0xFF
addq %rcx,(%rax) = 0xFF + 0x1 = 0x100
-
subq %rdx,8(%rax)我们也按照上面方式讲解
S -> %rdx
D -> 8(%rax) -> %rax + 8 -> 0x100 +8 -> 0x108 -> 0xAB
subq %rdx,8(%rax) = %rax + 8 - %rdx
这里的难点是8(%rax)为什么是%rax + 8,因为这个采用的是(基址 + 偏移量)寻址。
subq %rdx,8(%rax) = 0xAB - 0x3 = 0xA8
后面我就不那么详细讲解了直接列了
-
imulq $16,(%rax,%rdx,8)
S -> $16 -> 16
D -> (%rax,%rdx,8) -> %rax + 8 * %rdx -> 0x100+0x18 -> 0x118 -> 0x11
imulq $16,(%rax,%rdx,8) = 0x11 * 16 = 0x110
-
incq 16(%rax)
INC D 的定义是 D <- D + 1
所以根据定义有如下结果
D -> %rax + 16 -> 0x100 + 16 -> 0x110
所以计算结果为
incq 16(%rax) = 0x13 + 1 = 0x14
-
decq %rcx
解释如上
incq 16(%rax) = 0x1 - 1 = 0x0
-
subq %rdx,%rax
这个也不再详细解释了,有问题留言
subq %rdx,%rax = 0x100 - 0x3 = 0xFD
所以最后结果如下
指令 | 目的 | 值 |
---|---|---|
addq %rcx,(%rax) | 0x100 | 0x100 |
subq %rdx,8(%rax) | 0x108 | 0xA8 |
imulq $16,(%rax,%rdx,8) | 0x118 | 0x110 |
incq 16(%rax) | 0x110 | 0x14 |
decq %rcx | %rcx | 0x0 |
subq %rdx,%rax | %rax | 0xFD |