刚开始使用汇编(GAS),并且在这个短代码中有分段错误

Posted

技术标签:

【中文标题】刚开始使用汇编(GAS),并且在这个短代码中有分段错误【英文标题】:Just start using assembly (GAS), and has segmentation fault in this short code 【发布时间】:2017-05-09 08:23:44 【问题描述】:

这些天我正在学习 AT&T x86 组装。我正在编写将两个 32 位整数相乘而不使用“*”的代码。问题是调试器一直告诉我我有分段错误。这是我的代码。

.global _start


.data

a:
    .long 0

b:
    .long 0

count:
    .long 0

.text

_start:

    movl $0, %eax
    movl $a, %ebx
    movl $b, %ecx
    movl $0, %edx

    for_mult:
        cmpl $32, count
        je end_for_mult

        carry_bit:
            shr $1, %ecx
            jnc is_zero

            addl (%ebx), %eax

            is_zero:
                shl $1, %ebx

        incl count
        jmp for_mult
    end_for_mult:

done:
    movl %eax, %eax

调试器显示段错误出现在“addl (%ebx), %eax”,我不知道为什么。感谢您的帮助!

【问题讨论】:

您应该考虑shl $1, %ebxebx 的作用以及在下一轮 循环中这会如何影响addl (%ebx), %eax 当调试器出现分段错误并指向某个指令时,您可以检查所使用的内存地址(在这种情况下为ebx 中的值)。然后你可以检查你分配的内存(通常是.data/.rodata 部分标签),如果它指向你想要的地方。然后您可以开始搜索(可能通过一次执行代码 1 指令),为什么您离开了有效/预期的内存。顺便说一句,你还有一些免费的寄存器,为什么不为count 也使用一个呢?实际上为什么不只使用寄存器,并将结果存储到内存中呢?它通常更容易+更快。 【参考方案1】:

您正在混合地址和值。

把$符号去掉

movl a, %ebx
movl b, %ecx

(您的代码实际上将ab 的地址移动到寄存器而不是值!)

去掉%ebx周围的括号

addl %ebx, %eax

你想要的是 ebx 的值,而不是 ebx 指向的值。

【讨论】:

以上是关于刚开始使用汇编(GAS),并且在这个短代码中有分段错误的主要内容,如果未能解决你的问题,请参考以下文章

我的汇编程序中的分段错误

在 x86 汇编代码(GAS 语法)中有效乘以 2 的幂而不影响标志

为啥包装在函数中的 GAS 内联汇编为调用者生成的指令与纯汇编函数不同

defuse.ca 在线 GAS 汇编器接受 movb 和 movw 的 AT&T 语法,但不接受 movl?

16位汇编第三讲 分段存储管理思想

从 NASM 到 GAS 的翻译