文章目录
- 加载有效地址
-
- 一元操作符&二元操作符
-
- 移位操作
-
- 特殊的算数操作符
-
- 参考文献
写在前面:从腾讯实习回来之后,就感觉到自己的知识体系过于散乱。于是萌生了写一个自己的操作系统这样的心思,此为系列第一章,主要是讲解一些汇编知识的,内容大多从CSAPP中也可以获得。
本篇内容主要讲解汇编指令:算数以及逻辑相关操作指令
加载有效地址
加载有效地址指令leaq
实际上是movq
指令的变形。 它的指令形式是从内存读取数据到寄存器。它的第一个操作数看上去是一个内存引用,但该指令实际是将有效地址写入到目的操作数。
其使用格式如下:
比如说我们下面的这个例子:
long scale(long x,long y,long z)
{
long t = x+4*y+12*z;
return t;
}
我们展示其反汇编代码:
leaq (%rdi,%rsi,4),%rax
leaq (%rdx,%rdx,2),%rdx
leaq (%rax,%rdx,4),%rax
ret
leaq 练习题
刚刚讲了leaq
的基础用法,现在做两个题巩固一下,还是那样:往下滚动查看答案和解析:
![在这里插入图片描述](https://img-blog.csdnimg.cn/77bee26a56ef401e99a8ea45c55f3cd9.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rKh5pyJ5a-56LGh55qE6YeO5oyH6ZKIX2NvcHk=,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述](https://img-blog.csdnimg.cn/0faa1a6c8f504c00a1b85da59df93703.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rKh5pyJ5a-56LGh55qE6YeO5oyH6ZKIX2NvcHk=,size_20,color_FFFFFF,t_70,g_se,x_16)
练习题答案
![在这里插入图片描述](https://img-blog.csdnimg.cn/9b08bc11eec84e6eba2c24ad3758366b.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rKh5pyJ5a-56LGh55qE6YeO5oyH6ZKIX2NvcHk=,size_11,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述](https://img-blog.csdnimg.cn/4f966f8f5e344c2986d326cc32a40bed.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rKh5pyJ5a-56LGh55qE6YeO5oyH6ZKIX2NvcHk=,size_17,color_FFFFFF,t_70,g_se,x_16)
一元操作符&二元操作符
一元操作符,顾名思义:只有一个操作数,即是源又是目的。比如incq(%rsp)
会使栈顶的8字节元素+1。
指令 | 效果 | 描述 |
---|
inc D | D⬅D+1 | 加1 |
dec D | D⬅D-1 | 减1 |
neg D | D⬅-D | 取负数 |
not D | D⬅~D | 取补 |
二元操作符,则是第二个操作数既是源又是目的。比如指令subq %rax,%rdx
使寄存器%rdx
的值减去%rax
的值,等价于:%rdx = %rdx-%rax
。
注:
第一个操作数可以是立即数、寄存器或者内存位置
第二个操作数可以是寄存器或内存位置
但是!当第二个操作数为内存地址时,处理器必须从内存读出值,进行操作之后再写入内存中
指令 | 效果 | 描述 |
---|
add S,D | D⬅D+s | 加 |
sub S,D | D⬅D-s | 减 |
imul S,D | D⬅D*s | 乘 |
xor S,D | D⬅D^s | 异或 |
or S,D | D⬅Dls | 或 |
and S,D | D⬅D&s | 与 |
一元&二元 练习题
![在这里插入图片描述](https://img-blog.csdnimg.cn/cb49a6b6e0bd4013a5e6f582d9b737f1.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rKh5pyJ5a-56LGh55qE6YeO5oyH6ZKIX2NvcHk=,size_19,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述](https://img-blog.csdnimg.cn/bf6b4a2aba7d4554938db22b5b7d885a.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rKh5pyJ5a-56LGh55qE6YeO5oyH6ZKIX2NvcHk=,size_19,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述](https://img-blog.csdnimg.cn/34b3a7c91ed040a5a4612be78d216b9f.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rKh5pyJ5a-56LGh55qE6YeO5oyH6ZKIX2NvcHk=,size_20,color_FFFFFF,t_70,g_se,x_16)
练习题答案
![在这里插入图片描述](https://img-blog.csdnimg.cn/9366d9a43e7643c9abd9957098376806.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rKh5pyJ5a-56LGh55qE6YeO5oyH6ZKIX2NvcHk=,size_14,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述](https://img-blog.csdnimg.cn/35027fd9e4d544a68f80b9ee8e3051b1.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rKh5pyJ5a-56LGh55qE6YeO5oyH6ZKIX2NvcHk=,size_20,color_FFFFFF,t_70,g_se,x_16)
移位操作
移位操作会先给出移位量,然后第二项给出的是要移位的数。移位量可以是一个立即数或者放在单字节寄存器%cl
中。当移位操作对 w 位长的数据值进行操作,移位量是由%cl
寄存器的低 m 位决定的,这里2m = w,而高位则会被忽略。所以,当寄存器%cl
中的值为0xFF时,指令salb
会左移7位,salw
会左移15位,sqll
会左移31位,salq
会左移63位。
如下表所示,左移指令有两个名字:sal
和shl
。两者的效果是一样的,都是将右边填上0 。右移则是不同,sar
执行算术移位,会将扩充位填充符号位,而shr
执行逻辑移位,将扩充位填上0。
指令 | 效果 | 描述 |
---|
sal k,D | D⬅D<<k | 左移 |
shl k,D | D⬅D<<k | 左移(同sal) |
sar k,D | D⬅D>>k | 算数右移 |
shr k,D | D⬅D>>k | 逻辑右移 |
移位练习题
![在这里插入图片描述](https://img-blog.csdnimg.cn/0ad5f94a0ec947798509275699cd405f.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rKh5pyJ5a-56LGh55qE6YeO5oyH6ZKIX2NvcHk=,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述](https://img-blog.csdnimg.cn/ed05aeb24b354bb6a34676667a39a29b.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rKh5pyJ5a-56LGh55qE6YeO5oyH6ZKIX2NvcHk=,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述](https://img-blog.csdnimg.cn/aba424b13f24495c90de1e3c111ce6fb.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rKh5pyJ5a-56LGh55qE6YeO5oyH6ZKIX2NvcHk=,size_20,color_FFFFFF,t_70,g_se,x_16)
练习题答案
![在这里插入图片描述](https://img-blog.csdnimg.cn/f94ceed4b58d414d96eb530ddc11d2ad.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/e4a34033b8f24fa182b37d3c842429b0.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rKh5pyJ5a-56LGh55qE6YeO5oyH6ZKIX2NvcHk=,size_19,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述](https://img-blog.csdnimg.cn/3b2d26f76e3943b19bb344e9fe4b5e7c.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rKh5pyJ5a-56LGh55qE6YeO5oyH6ZKIX2NvcHk=,size_20,color_FFFFFF,t_70,g_se,x_16)
特殊的算数操作符
下表中的指令提供了一些不常用的特殊的算数操作:
![在这里插入图片描述](https://img-blog.csdnimg.cn/aad9c36eaa664edfb364037ed85f719e.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rKh5pyJ5a-56LGh55qE6YeO5oyH6ZKIX2NvcHk=,size_17,color_FFFFFF,t_70,g_se,x_16)
可以在表中看到有两个乘法指令:imulq
、mulq
。一个是有符号乘法,一个是无符号乘法,这两个可以用来计算两个64位的值的全128位乘积。这两个指令都要求一个参数必须在寄存器%rax
中,而另一个作为指令的源操作数给出。之后,乘积存放在寄存器%rdx
(高64位)和%rax
(低64位),下面的例子给出了如何计算乘积:
#include <inttypes .h>
typedef unsigned __int128 uint128_ t;
void store_uprod(uint128 _t *dest, uint64_t x,uint64_t y) {
*dest = x * (uint128_t) y;
}
这个例子得到的汇编代码如下:
store_uprod:
movq %rsi, %rax
mulq %rdx
movq %rax, (%rdi)
movq %rdx, 8(%rdi)
ret
到目前为止,我们都没有介绍除法操作符和取模操作。这些操作是由单操作数除法指令所提供。有符号除法指令idivl
将寄存器%rdx
(高64位)和%rax
(低64位)中的128位数作为被除数,而除数作为指令的操作数给出。指令将商存储在寄存器%rax
,将余数存在寄存器%rdx
中。以下例子给出了除法的实现:
void remdiv(long x,long y,long *qp,long*rp)
{
long q = x / y;
long r = x % y;
*qp = q;
*rp = r;
}
其汇编实现如下:
remdiv :
movq %rdx, %r8
movq %rdi, %rax
cqto
idivq %rsi
movq %rax, (%r8)
movq %rdx, (%rcx)
ret
注:
无符号除法使用divq
指令,通常寄存器%rdx会事先设置为0
练习题
![在这里插入图片描述](https://img-blog.csdnimg.cn/049e135616514846a80ef0f899e28d26.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rKh5pyJ5a-56LGh55qE6YeO5oyH6ZKIX2NvcHk=,size_20,color_FFFFFF,t_70,g_se,x_16)
练习题答案
movq %rdx, %r8
movq %rdi, %rax
movl $0, %edx
divq %rsi
movq %rax, (%r8)
movq %rdx, (%rcx)
ret
参考文献
[1] 深入理解计算机系统 第三章 程序的机器级表示
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)