Can't understand the error: invalid effective address on mov rax , qword [ rbp-24 - rbx * 8]
Can't understand the error: invalid effective address on mov rax , qword [ rbp-24 - rbx * 8]
我想学习 asm,来自 C
一本书建议尝试实现这个算法,这是一个非常简单的排序算法
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 行我得到错误
错误:无效的有效地址
起初我认为这是一个对齐错误(因此排序函数开头的 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
的指针作为基地址,而且也不支持;基地址必须来自寄存器。方便的是,你已经在寄存器 rdi
中有了 array
的地址,所以我想你想要的只是
mov rax, qword [rdi + rbx * 8]
只是改进代码时的一般提示:使用汇编语言的主要原因是速度,而实现速度的最重要方法是尽量减少内存访问。您真的不想将局部变量保存在堆栈中并在每次触摸它们时访问内存。机器有很多寄存器,所以只需为每个变量选择一个寄存器并将其保存在那里。
如果您一直试图通过阅读未优化的编译器汇编输出来学习,您可能会养成过度使用内存的习惯; non-optimizing 编译器会将所有内容保存在堆栈中,以便在需要时具有一致的位置和一致的地址。但是尝试启用优化,你会发现它神奇地消失了,一切都尽可能地用寄存器完成。这才是你应该努力争取的。
我想学习 asm,来自 C
一本书建议尝试实现这个算法,这是一个非常简单的排序算法
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 行我得到错误 错误:无效的有效地址
起初我认为这是一个对齐错误(因此排序函数开头的 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
的指针作为基地址,而且也不支持;基地址必须来自寄存器。方便的是,你已经在寄存器 rdi
中有了 array
的地址,所以我想你想要的只是
mov rax, qword [rdi + rbx * 8]
只是改进代码时的一般提示:使用汇编语言的主要原因是速度,而实现速度的最重要方法是尽量减少内存访问。您真的不想将局部变量保存在堆栈中并在每次触摸它们时访问内存。机器有很多寄存器,所以只需为每个变量选择一个寄存器并将其保存在那里。
如果您一直试图通过阅读未优化的编译器汇编输出来学习,您可能会养成过度使用内存的习惯; non-optimizing 编译器会将所有内容保存在堆栈中,以便在需要时具有一致的位置和一致的地址。但是尝试启用优化,你会发现它神奇地消失了,一切都尽可能地用寄存器完成。这才是你应该努力争取的。