由cmp引起的分段错误

时间:2018-02-03 14:11:51

标签: c assembly segmentation-fault x86-64

我目前正在尝试学习汇编语言。但我被卡住了。 假设我有这个C代码:

__asm__ ("movq $100, %rax;"
        ".loop:"
        //Some code
        "decq %rax;"
        "cmpq $0, (%rax);"
        "jnz .loop;"
);

现在我想用汇编语言做同样的事情。我试过这样的话:

<Page.BottomAppBar>

以seg错误编译并运行结果。如果我删除cmpq行,它不会出错。但当然程序不会终止。

所以基本上我的问题是我在这里做错了什么?

提前致谢。

3 个答案:

答案 0 :(得分:8)

以下说明:

cmpq $0, (%rax)

正在访问rax寄存器指定的内存地址,其值为99

第一个内存页面映射。该内存地址99属于第一个内存页面。因此,上述访问会导致分段错误。

你不想要间接,而是你想要的:

cmpq $0, %rax

也就是说,您希望与rax内容进行比较,而不是rax指定的内存地址中的内容。< / p>

然而,请考虑优化 cmp指令

decq %rax紧接在cmp $0, %rax指令之前,如果ZF为零,则设置rax。然后根据ZF标志的状态执行条件跳转:

decq %rax
cmpq $0, %rax
jnz .loop

dec指令会影响ZF标记(如cmp所示),因此如果递减rax结果为零,则会设置ZF。您可以利用这一事实,并在jnz之后直接放置dec。您根本不需要cmp

decq %rax
jnz .loop

答案 1 :(得分:7)

cmpq $0, (%rax)

该指令将尝试读取rax中地址的内存。

第一次

rax将是99。地址99未映射,因此您的程序会出现段错误。

您打算将rax中的值与0进行比较,因此请删除括号。

cmpq $0, %rax

答案 2 :(得分:3)

从%rax中删除括号以获取rax的值。添加括号基本上告诉汇编程序,&#34;嘿! rax持有一个地址,请返回该地址中的内容&#34;。

因此,

cmpq $0, %rax

是你需要做的。