当前位置: 首页 > 知识库问答 >
问题:

无法理解错误:mov rax上的有效地址无效,qword[rbp-24-rbx*8]

赵钊
2023-03-14

我想学习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行,我得到了错误:无效的有效地址

起初我认为这是一个对齐错误(因此排序函数开始时的推送四字)
然后我尝试使用movq指令(由于其他原因显然不起作用,我已经阅读了指令手册)
向内存地址移动似乎可行,即使被寄存器引用(至少mov[rax],qword[rbp-24-rbx*8]编译),但我几乎看不出这样做有什么意义)我可能用编译的lea来修复它,但我想要值,不是吗,mov rax,,qword[rbp-24-rbx*8]给出了rbp-24-rbx*8所指的值?

由于我在代码中的四个不同点(第38行之后)遇到了相同的问题,我完全卡住了,不知道现在该尝试什么
有人能解释一下为什么这不能编译,如果可能的话给出一个解决方案(或至少提示)

共有1个答案

米元凯
2023-03-14
mov rax , qword [  rbp-24 - rbx * 8]

这从表面上看是非法的,因为SIB寻址模式只能添加缩放索引寄存器(此处rbx*8);它不能减去它。但是如果您想要数组(i),那么您无论如何都要添加它,因为这里的rbx对应于i

然而,似乎您正试图使用存储在rbp-24的指针作为基址,这也不受支持;基址必须来自寄存器。方便的是,您已经在寄存器rdi中拥有了数组的地址,所以我认为您想要的只是

mov rax, qword [rdi + rbx * 8]

在改进代码时,有一个通用提示:使用汇编语言的主要原因是速度,而实现速度的最重要方法是最小化内存访问。你真的不想把局部变量保存在堆栈上,每次触摸它们都要访问内存。机器有很多寄存器,所以只需为每个变量选择一个寄存器并将其保留在那里。

如果您一直试图通过读取未优化的编译器程序集输出来学习,那么您可能会养成过度使用内存的习惯;非优化编译器将保留堆栈上的所有内容,以便在需要时具有一致的位置和地址。但是试着启用优化,你会看到它神奇地消失,并且尽可能多地使用寄存器完成所有事情。这是你应该努力争取的。

 类似资料:
  • 我创建了一个AngularJS应用程序,没有 我的一个输入字段是number。 现在我如何显示错误消息没有从名称? 当我在字段中输入任意字符时,它会在输入类中显示ng invalid ng invalid number tag(屏幕截图1)。当输入一些数字时,它会显示ng有效类(屏幕截图2)。所以我的代码是works。 但问题是我的错误消息不起作用。 我遵循以下教程:http://codepen.

  • 根据postgresql(postgis)方法,此几何是有效的,但是Elasticsearch在索引时抛出illegal_argument_exception错误 https://gist.github.com/owexroasia/127c61ee41304fe2d2d0e0015216a780 {"type":"mapper_parsing_exception","原因":"未能解析类型[ge

  • 问题内容: 我想检查请求url的状态码但获取代码 这是我的代码 堆栈跟踪 问题答案: 我认为,此问题是由Java尝试使用IPV6地址引起的,原因是您的操作系统不支持IPV6地址,或者您的操作系统没有正确设置IPV6地址来处理它。 您可以强制Java使用具有以下属性的IPV4地址: -Djava.net.preferIPv4Stack = true

  • 我有以下设置: < li >端口8080上的Spring Cloud网关 < li >路由/用户到端口9000上的Spring Rest API(称为用户) < li >路由/字符到端口9001上的Spring Rest API(称为字符) < li >端口8090上的Spring Cloud配置服务器 网关和两个RestAPI应用程序连接到云配置以拉取配置。应用程序本身可以正确启动,并可以通过各

  • 问题内容: 我正在努力了解forEach和map之间的区别。在以下渲染函数中,如果将“ forEach”替换为“ map”,则它将起作用。我不明白为什么它不能与“ forEach”一起使用。两种方法都同时提供{item.id}和{item.text}。那么,为什么在使用“ forEach”时没有设置“ TodoItem”的道具呢? 因此,如果“ forEach”不返回任何信息,那么这也不起作用: