系列文章目录
程序的机器级表示:
CSAPP第三章的目录
- 历史观点
- 程序编码
- 数据格式
- 访问信息
- 算数和逻辑操作
- 控制
- 过程
- 数组分配和访问
- 异质的数据结构
- 在机器级程序中奖控制与数据结合起来
- 浮点代码
九曲阑干的课程目录:
- 机器级代码(至书的3.4.1)
- 数据传送指令(至书的3.5.4)
- 条件码寄存器
- 跳转指令以及bomblab_ev
- 过程
- 多维数组与结构体
- 缓冲区溢出
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
参考
这里将参考列出来:
一、数据传送指令(Data Movement Instruction)
这里要注意:你要想将一个内存地址搬到另一个内存地址中去,不能用一条指令去完成。也就是
mov (%rax) (%rbx)
这条指令是错误的!!!
应该这样:
可以这样来理解:
看一下几个mov
指令的例子:
1.1 详细说明
例如,假设我们有一个寄存器 %rax
,如果我们说:寄存器值:
%rax
中的值是 0x100。- 内存地址 0x100 的值为 0xAB
mov %rax, %rbx ; 把 %rax 寄存器中的值 (0x100) 复制到 %rbx 寄存器%rbx 现在也是 0x100
mov $0x1, (%rax) ; 把数值 0x1 存储到内存地址 %rax 指向的位置(即内存地址 0x100)
mov (%rax), %rbx ; 从内存地址 0x100 读取数据,即 0xAB,并将这个值存储到 %rbx
(%rax)
有点像指针解引用,就这么理解会很快地读懂
1.2 C语言和汇编的例子
1.3 源操作数向目的操作数扩展
- 零扩展
这个类似于无符号数中short类型向int类型转换发生零扩展
- 符号扩展
这个类似于有符号数short类型向int类型转化会发生符号扩展
- 特殊情况
详情见PPT,挺难记住的。记住要查指令手册!!!作为教学内容,我们只需要记住原理就行了。
二、压入和弹出栈数据(Stack)
栈作为基本的数据结构这里不过多赘述。
我们这里讲的栈是系统运行时栈,本质上是操作系统中的内存的一块空间
栈的生长方向是从高地址到低地址,与之相反的则是堆。
2.1 push和pop操作
三、算数和逻辑操作
3.1 加载有效地址
leaq 实际上是 movq 指令的变形。操作是从内存读数据地址到寄存器。
leaq 在实际应用中常常不用来取地址,而用来计算加法和有限形式的乘法
leaq 9(rdi, rsi, 4), rax;
//x in rdi,y in rsi。此操作实际上等于将 x+4*y+9 的结果存入 rax
来看一个例子:
解释:
那为什么不直接用最下面的一条呢?直接让s=12
?
这里要注意:在上一章文章中讲过s只能等于[1, 2, 4, 8],是因为变量寻址针对的是数组
通过上面的分析我们发现,它没有访问内存!!! 由于 LEAQ
可以在不访问内存的情况下执行运算,因此在某些情况下可以作为优化工具使用。
3.2 Unary Operation(一元操作)
只有一个操作数,这种操作数,它既是目的操作数,又是源操作数。
3.3 Binary Operations(二元操作数)
上面三个是算数操作,下面三个是逻辑操作
原内存:
操作后的内存:
3.4 Shift Operations(移位)
第一项是移位量,然后第二项是要移位的数
3.4.1 移位量 Shift Amount
移位操作的移位量可以是:
- 一个立即数
- 放在单字节寄存器
%cl
中。该寄存器长度是8bit(0~255)
怎么理解上面的事情呢?
原书给出的解释:
说实话这个解释比较弯弯绕,他其实就是取模的一个操作。
在汇编语言中,使用 %cl
寄存器作为移位量时,实际的移位数是 %cl
的值对某个数取模(取余数)的结果。这是为了防止移位数超过操作数的位数,这里的操作数位数指的是你要操作的数据的大小(如8位、16位、32位或64位)。在32位系统中,如果使用 %cl
寄存器作为移位数,并对一个32位寄存器如 %eax
进行操作,移位数的有效范围是0到31位。如果 %cl
的值超过了31,那么实际的移位数将是 %cl % 32
。同理,在64位系统中,对于64位寄存器如 %rax
,有效的移位范围是0到63位,如果超出则取 %cl % 64
。
让我们通过一个具体的例子来说明这一点:
假设 %cl
寄存器的值为 100
,我们想在32位系统中对 %eax
寄存器进行左移操作。正常情况下,我们不能直接移动100位,因为这超出了 %eax
寄存器的最大位数(32位)。因此,实际的移位数将是 100 % 32 = 4
。
这里是具体的汇编代码示例:
mov $100, %ecx ; 将100移入cl寄存器,注意cl是ecx的低8位
mov $1, %eax ; 假设eax初始值为1
shl %cl, %eax ; 左移cl指定的位数,即左移4位(100 % 32)
在这个例子中,%eax
寄存器原始的值是 1
(二进制为 0000 0001
)。经过左移4位操作后,%eax
寄存器的值变为 0001 0000
,即十六进制的 0x10
。
通过这个例子,你可以看到 %cl
中的移位数如果超出了操作数的最大位数,实际执行的移位数是取模后的结果。这样的设计可以防止不必要的错误和异常行为,确保汇编指令的有效和安全执行。
3.5 不常见的特殊指令
这个完全没必要记住,要用的时候查手册就行了
3.6 例子
知道怎么写下面这个例子,就代表这小节内容掌握得差不多了
总结
操作 源操作数 目的操作数
- 数据传送指令
- 压栈入栈指令,
%rsp
栈顶指针存放的寄存器 - 算数逻辑操作:
- 一元操作
- 二元操作
- 逻辑操作
- 移位操作
- 特殊操作
查看:有道云笔记
内容: