我想学习C语言的asm
一本书建议尝试实现此算法,这是一种非常简单的排序算法
begin
for i = 0 to len-1
small = arr(i)
index = i
for j = i to len-1
if ( arr(j) < small ) then
small = arr(j)
index = j
end_if
end_for
arr(index) = arr(i)
arr(i) = small
end_for
end_begin
我的代码的开头是(可以根据需要提供其余内容)section .bss
section .data
len dq 5
array dq 1 , 3 , 6 , 8 , 2
section .text
global _start
_start:
mov rdi , [len]
mov rsi , array
call sort
exit
sort:
push rbp
mov rbp,rsp
push qword 0 ; i_counter = rbp-8
push rdi ; len = rbp-16
push rsi ; *array = rbp -24
push qword 0 ; j = rbp - 32
dec qword [rbp-16]
i_loop:
mov r8 , [rbp-16]
cmp [rbp-8], r8 ; if counter = len - 1 (decreased above)
je end_i_loop
mov rbx , [rbp-8]
mov rax , qword [ rbp-24 - rbx * 8] ; small = array(i) and line 38
mov rcx , [rbp-8] ; index = i
mov [rbp - 32 ] , rcx ; j = i
在第38行,我得到了错误错误:有效地址无效
起初,我认为这是对齐错误(因此,sort函数开始处的push四字)
然后我尝试了movq指令(由于其他原因,该指令显然不起作用,因为我已经阅读了指令手册)
即使被寄存器引用(至少是mov [rax],qword [rbp-24-rbx * 8]编译),向内存地址移动似乎也可以,但是这样做几乎没有意义。
我可能会用lea来修复它,它会编译,但是我想要这个值,不mov rax,qword [rbp-24-rbx * 8]给出了rbp-24-rbx * 8指向的值吗?
由于我在代码中的四个不同点(第38行之后)都遇到相同的问题,因此我完全陷入了困境,不知道现在要尝试什么
有人可以解释为什么它不能编译,并在可能的情况下给出解决方案(或至少提示)
最佳答案
mov rax , qword [ rbp-24 - rbx * 8]
从表面上看这是非法的,因为SIB寻址模式只能添加缩放的索引寄存器(此处为rbx * 8
)。它不能减去它。但是,如果您想要array(i)
,则无论如何都要添加它,因为此处的rbx
对应于i
。但是,似乎您正在尝试使用存储在
rbp-24
中的指针作为基址,并且也不支持该指针;基址必须来自寄存器。方便地,您已经在array
寄存器中有了rdi
的地址,所以我认为您想要的只是mov rax, qword [rdi + rbx * 8]
只是改善代码的一般提示:完全使用汇编语言的主要原因是速度,而达到速度的最重要方法是最小化内存访问。您确实不希望将局部变量保留在堆栈中,并且每次触摸它们时都访问内存。机器有很多寄存器,因此只需为每个变量选择一个寄存器并将其保存在那里。如果您一直试图通过读取未优化的编译器程序集输出来学习,则可能会养成过度使用内存的习惯。非优化的编译器会将所有内容保留在堆栈中,因此它具有一致的位置和一致的地址(如果需要)。但是尝试启用优化,您会发现所有这些魔术都消失了,并且尽可能多地使用寄存器完成了所有工作。这是您应该努力争取的更多东西。
关于linux - 无法理解: invalid effective address on mov rax , qword [ rbp-24 - rbx * 8]错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/64563796/