接上篇文章,开始了解算术和逻辑操作,控制操作,过程指令,C语言中嵌入汇编
算术与逻辑分为四类,1。加载有效地址 2。一元与二元操作 3。移位操作 4。乘除法
其中加载有效地址是指只把本来要把内存中提取数据的那些地址提取出来,并不进行内存的操作:例如M[R[Ea]+R[Ei]*4+4]转换成汇编4(Ea,Ei,4)对内存地址为R[Ea]+R[Ei]*4+4进行操作提取数据,但加载有效地址指令leal(load effective address)并不对内存提取数据,而只提这个地址,这个就相当于C语言里面的&取地址符。但大家可能会问,这个指令与算术有什么关系呢?利用它,可以方便实现一些简单的运算:比如:
假设%edx =x,那么5x+7的实现方式:leal 7(%edx,%edx,5),%eax,用到上节寻址方式就能简单实现这样的运算。再举个例子吧:假设%eax=x,%edx=y,用汇编语言写出5x+4y+7的表达式:首先把4y+7实现了然后把 结果写回%edx中,leal 7(,%edx,4),%edx.再把5x+(4y+7)实现把结果写到寄存器%eax中,leal (%edx,%eax,5) ,%eax.这样实现加法运算确实是很方便的。
其中一元与二元操作,仅是针对操作数进行区分的算述运算。
incl (%esp),栈顶元素加一
decl (%esp),栈顶元素减一
negl (%esp),栈顶元素取负
notl (%esp),栈顶元素取补
这上面的指令都是一元操作,下面是二元操作
addl s,d. s与d相加,结果存放到D中
subl S,D。S与D相减,结果存在D中
还有很多二元操作指令,可以查询相关的汇编语言教程
移位操作是指左右移动,移动多少位这么一个说法,很像C语言中的移位操作
在这里面有必要了解一下imull,mull,cltd,idivl,divl五个指令,因为他们的操作关联了特定的寄存器
| 指令 | 效果 | 描述 |
|
imull S |
R[%edx]:R[%eax]<- S*R[%eax] | 有符号全64位乘法 |
| mull S | R[%edx]:R[%eax]<- S*R[%eax] | 无符号全64位乘法 |
| cltd | R[%edx]:R[%eax]<-符号扩展(R[%eax]) | 转换为四字(一字为16位) |
| idivl S |
R[%edx] <- R[%edx]:R[%eax] mod S R[%eax] <- R[%edx]:R[%eax] *S |
有符号除法 |
| divl |
R[%edx] <- R[%edx]:R[%eax] mod S R[%eax] <- R[%edx]:R[%eax] *S |
无符号除法 |
从上面的表中,我们可以看出除法中商是放在R[%eax]中,模是放在R[%edx]中的,所以在编写汇编程序时要记住这些特殊的指令。
下面来看一下汇编例子x除y,假设x=8(%esp),y=12(%esp)
movl 8(%esp) ,%eax #把X存放到寄存器%eax
cltd %eax #把X扩展成立64位
idivl 12(%esp) #除以Y
pushl %eax #商放在%eax,然后把结果放到栈顶
pushl %edx #模存放到%edx,在后把模存放到栈顶
控制
要实现控制过程,必须有一些根据,汇编语言中把这些根据统称为条件码:CF,进位标志,它可以用来检查无符号操作数的溢出。
ZF,零标志,最近操作得出的结果为0
SF,符号标志,最近操作得到的结果为负数
OF,溢出标志,最近的操作导致一个二进制补码溢出,可为正或负溢出
我应该如何设置这些标志呢?
汇编语言为我们提供了一系列的指令:CMPB S2,S1。是对S1-S2 比较字节,并设置条件码。TESTB S2,S1是对S1&S2测试。
我们又应该如何读取这些标志呢?
同样也有一堆的汇编语言指令,比如setl,sete,setne,sets,setns,setg,setge,setl,setle,seta,setae,setb,setbe.

