Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用;lea($30,%edx),%eax添加edx和30并将其放入eax_C_Assembly - Fatal编程技术网

C 使用;lea($30,%edx),%eax添加edx和30并将其放入eax

C 使用;lea($30,%edx),%eax添加edx和30并将其放入eax,c,assembly,C,Assembly,我正在准备明天的期中考试,前一期中考试的一个问题是: 考虑下面的C函数。编写相应的汇编语言函数以执行相同的操作 int myFunction (int a) { return (a + 30); } 我写的是: .global _myFunction _myFunction: pushl %ebp movl %esp, %ebp movl 8(%ebp), %edx lea ($30, %edx), %eax leave ret

我正在准备明天的期中考试,前一期中考试的一个问题是:

考虑下面的C函数。编写相应的汇编语言函数以执行相同的操作

int myFunction (int a) 
{ 
    return (a + 30); 
} 
我写的是:

.global _myFunction
_myFunction:
    pushl %ebp
    movl %esp, %ebp
    movl 8(%ebp), %edx
    lea ($30, %edx), %eax
    leave
    ret
其中a为edx,a+30为eax。在这种情况下使用lea正确吗?是否需要这样做

lea ($30, %edx, 1), %eax 

谢谢。

如果您希望使用
leal
简单地添加30,那么您应该这样做:

leal 30(%edx), %eax
表示法为移位(
基址寄存器
偏移寄存器
标度乘法器
)。位移放置在外侧
30
被添加到
edx
并存储在
eax
中。在AT&T/GAS表示法中,可以同时省去偏移量和乘数。在我们的示例中,这给我们留下了本示例中的等效值
base+displacement
edx+30

赵也提出了一个很好的观点。假设教授要求您优化代码。
myFunction
不使用局部变量,本身也不需要堆栈空间,这一事实存在一些低效性。因此,可以删除所有堆栈帧的创建和销毁。如果删除堆栈帧,则不再推%ebp。这意味着您的第一个参数
inta
位于
4(%esp)
。考虑到这一点,您的功能可以简化为以下简单功能:

.global _myFunction
_myFunction:
    movl 4(%esp), %eax
    addl $30, %eax
    ret

当然,当您更改函数以使其需要在堆栈上存储内容时,您必须将堆栈帧代码放回(
pushl%ebp
pushl%ebp
leave
等)

看起来至少是编译器生成的。但是,是否有任何原因表明该函数不仅仅是
movl4(%esp),%eax
addl$30,%eax
ret
?如果您从未实际使用堆栈(即:除非您自己调用函数,否则为局部变量保留空间等),则构建堆栈帧不是很有用。如果您不需要设置标志,lea通常比add快。@MichaelPetch,我实际上读到了其他方法。据我所知,
lea
防止指令重新排序,因为在执行
lea
指令之前需要填充标志寄存器。在任何非古代CPU上使用
lea
而不是
add
应该是个坏主意。@Kay这是正确的。不过,如果你看看我的评论,我一般都会这么说。大多数优化器会查看上下文,以确定add或lea在任何给定情况下是否更有意义。寻址模式的乘法部分不能为零:如果存在,它总是1,2,4,8中的一个。但是,它所应用的操作数是可选的。base+置换是一种特殊情况。我最初使用“有效”一词,因为从观察者的角度来看,缺少偏移寄存器(索引)和乘数似乎等于零。在引擎盖下
base+displacement
产生一种特殊的单字节地址模式编码,既不指定偏移寄存器(索引),也不指定乘法器。显然,一个副作用是,如果不指定offsetregister,则汇编程序将不允许在没有offsetregister(索引)的情况下指定任何标量,因为指令中根本没有编码scalarmultiplier。