【问题标题】:Function calculating maximum value in AT&T x86 assemblyAT&T x86 汇编中计算最大值的函数
【发布时间】:2023-03-10 20:22:01
【问题描述】:

我正在尝试编写这个名为 maximum 的函数,它将从数字列表中返回最大值,我想使用可以指示从哪里开始的标签。当地址(我用于计算下一个值在哪里)超过列表时,函数将跳转到循环的末尾。

不幸的是,在组装程序并运行它后,我得到了分段错误。

我要求找出我的代码中的错误。我尝试使用 GDB 调试器,但还是不行。

.section .data
list_1:
 .long 5,3,6,2,7,78
list_2:
 .long 33,23,52,6,7,89,22,33,6
list_3:
 .long 22,33,10,45,6,34
end_list_3:

 .section .text

 .globl _start
 .globl maximum
_start:

 pushl list_2
 pushl list_1
 call maximum
 addl $8, %esp
 movl %eax, %ebx


 mov $1, %eax
 int $0x80
                        #maximum function: 1 param - location of first value
                        #                  2 param - location of last value+4
 .type maximum STT_FUNC
maximum:
 pushl %ebp
 movl %esp, %ebp

 movl 8(%ebp),%ebx      # %ebx = location of first value
 movl 12(%ebp), %ecx    # %ecx location of last value + 4

 movl (%ebx), %eax      # %eax will store current highest value

 movl $0, %esi          # %esi will be our index

start_loop:
 incl %esi
 lea (%ebx,%esi,4), %edx
 cmpl %edx, %ecx
 je exit_loop
 movl (%ebx,%esi,4), %edi       #%edi is a current examined value
 cmpl %eax, %edi
 cmovg %edi, %eax
 jmp start_loop
exit_loop:

 movl %ebp, %esp
 popl %ebp
 ret

【问题讨论】:

  • 我认为汇编代码是重复的。正常吗?
  • 调试器告诉你什么?无论如何,at&t 语法需要$ 立即符号,所以你已经在pushl list_2 出错了,因为你想推送地址而不是值。当然,list_1 也一样。可能还有其他错误。
  • @Jester,就是这样,现在运行良好,谢谢!

标签: assembly x86 att


【解决方案1】:

问题在于推送参数,我想推送标签地址但正在使用:

pushl   list_2
pushl   list_1

list_1 和 list_2 被视为将被压入堆栈的值的地址,因此这是压入内存源操作数而不是立即数。

改为:

pushl   $list_2
pushl   $list_1

在这个小改动之后,程序按计划运行,现在这两条指令直接推送地址:list_1 和 list_2,这正是我想要的。

谢谢@Jérôme Richard 和@Jester。

【讨论】:

  • 我相信你想要pushl $list_2pushl $list_1
  • @fuz:是的,push &list_1 是一个语法错误。我修复了这个答案。
【解决方案2】:

您可以使用调试器轻松找到原因。我建议你使用 gdb(尤其是使用 layout asmni 命令)。

段错误位于这一行:

    mov (%ebx), %eax

这是正常的,因为 ebx 中存储的值是整数 (5) 而不是有效指针。 您可能想在以下说明中使用 lea 而不是 movl:

    movl 8(%ebp),%ebx      # %ebx = location of first value
    movl 12(%ebp), %ecx    # %ecx location of last value + 4

【讨论】:

  • 这是正确的,因为我推送地址,而且我想将它们加载到寄存器中。将 push list_1 更改为 push $list_1 并将 list_2 更改为 push $list_2 后,程序按我的意愿运行。你能提供一些让我熟悉gdb的链接吗?有趣的是 gdb 如何强调 mov (%ebx), %eax 中的段错误。
  • 好的。对于 gdb,互联网上有很多(大部分都很糟糕)教程。您可以以this onethis one 开头。
猜你喜欢
  • 2018-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-25
  • 1970-01-01
  • 2017-07-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多