【CSAPP-深入理解计算机系统】3-5.指令与条件码_哔哩哔哩_bilibili
【CSAPP-深入理解计算机系统】3-6.跳转指令与循环_哔哩哔哩_bilibili
程序的机器级表示_晨哥是个好演员的博客-CSDN博客_程序的机器级表示
leaq指令、
加载有效地址(load effective address
)指令leaq
实际上是movq
指令的变形,它的指令形式是从将内存地址读写到到寄存器当中,但实际根本未引用内存,也没有从内存地址处读取数据,它的第一个操作数看上去是内存引用,但该指令并不是从指定位置读入数据,而是将有效地址写入到目的操作数。

以上为leaq
指令将有效地址值写入寄存器中的过程,即加载有效地址。leaq
不仅可以加载有效地址,还可表示加法和有限乘法运算,对下述代码进行编译:

汇编得到的汇编代码指令如下:
leaq (%rdi,%rsi,4), %rax
leaq (%rdx,%rdx,2), %rdx
leaq (%rax,%rdx,4), %rax
ret
x存放在rdi寄存器中,y存放在rsi寄存器中,z存放在rdx寄存器中,那么第一条指令将rdi+4*rsi放入rax中,即表示x+4y;第二条指令表示将3z写入rdx寄存器;第三条指令则是将rax存放的x+4y与4rdx相加结果写入rax,此时rax存放的是x+4y+12z的结果,最终rax寄存器作为返回值返回即可。leaq
指令能执行加法和有限的乘法,在编译如上简单的算术表达式时,是很有用处的。

一元和二元操作、移位操作、特殊算术操作、


移位操作:


我们根据具体代码举例说明移位操作,示例如下:
因为w是两个字节,16位,即2的4次方为16。

我们分析一下这个代码第3行,对应的汇编指令:

上图rdx的值为z,rax通过第一条指令,存放3z的值,然后第二条指令左移4位等同于乘以2的4次方即16,所以这两条指令最终计算的是48z的值,存放至rax寄存器中。为什么编译器不直接使用乘法指令来实现这个运算呢?主要是因为乘法指令的执行需要更长的时间,因此编译器在生成汇编指令时,会优先考虑更高效的方式。
条件码、
条件码寄存器其实也称为标志寄存器,其具有三种作用:
- 用来存储相关指令的某些执行结果;
- 用来为CPU执行相关指令提供行为依据;
- 用来控制CPU的相关工作方式。


以下是8086相关标志位:

条件码寄存器(状态寄存器)的值是由ALU
在执行算术和运算指令时写入的,下图中的这些算术和逻辑运算指令都会改变条件码寄存器的内容:

对于不同的指令也定义了相应的规则来设置条件码寄存器。例如:
- 逻辑操作指令
xor
,**进位标志(CF)和溢出标志(OF)**会置0
; - 对于
inc
加一指令和dec
减一指令会设置溢出标志(OF)和零标志(ZF),但不会改变进位标志(CF)。


关于条件码使用,我们举例看下如下代码以及其汇编指令:

gcc -Og -S a.c
得到汇编指令为:
comp:
cmpq %rsi, %rdi // a-b
sete %al //根据标志设置寄存器al的值
movzbl %al, %eax //把寄存器al的值复制到寄存器eax上,并进行零扩展
ret
上面已经介绍了cmp
指令,cmp
指令是根据两个操作数的差来设置条件码寄存器,如果计算得到的结果为0,则设置ZF为1,否则为0。cmp
指令和减法指令sub
类似,也是根据两个操作是的差来设置条件码,二者不同的是cmp
指令只是设置条件码寄存器,并不会更新目的寄存器的值。
在这个例子中,指令sete
根据需标志(ZF)的值对寄存器al
进行赋值,后缀e
是equal
的缩写。如果零标志等于1
,指令sete
将寄存器al
置为1
;如果零标志等于0
,指令sete
将寄存器al
置为0
。

然后mov
指令对寄存器al
进行零扩展,最后返回判断结果,存放至rax
寄存器中。
下面看一个复杂例子,代码如下:

转成汇编指令后:


异或是相同为0,不相同为1!!!不溢出设置OF为0,溢出设置OF为1。
这里是8位的有符号数,数值范围是-128~+127 。

溢出的判断方法有三种:
1.由计算结果来判断
当出现:“正+正=负、负+负=正、正-负=负、负-正=正”的时候,都是产生了溢出。
2.由计算过程中的进位来判断
当出现:最高位的进位(即符号位的进位)和“次高位”的进位 不相同 的时候,就是产生了溢出。
3.由计算后的标志位来判断
当出现:OF = 1 时,就是产生了溢出。
判断a<b
是否为真,需要首先判断a-b
的值,a-b<0
设置SF=1
,反之SF=0
,然后判断是否正溢出或负溢出,溢出置OF=1
,反之OF=0
;计算SF^OF
,若结果为1
,则a<b
为true
;反之a<b
为false
。所以,综上可发现,根据符号标志(SF)和溢出标志(OF)的异或结果,可以对a
小于b
是否为真做出判断。更多相关set
指令如下:

Comments 2 条评论
哈哈
@原批 哈哈