由cmp引起的分段错误

Gig*_*ull 6 c assembly x86-64 segmentation-fault

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

for ( int i = 100; i > 0; i-- ) {
  // Some code
}
Run Code Online (Sandbox Code Playgroud)

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

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

编译并运行seg故障.如果我删除cmpq行,它不会出错.但当然程序不会终止.

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

提前致谢.

眠りネ*_*ネロク 8

以下说明:

cmpq $0, (%rax)
Run Code Online (Sandbox Code Playgroud)

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

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


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

cmpq $0, %rax
Run Code Online (Sandbox Code Playgroud)

也就是说,你要比较针对内容rax,而不是在内存地址的内容由指定rax.


然而考虑优化cmp指令:

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

decq %rax
cmpq $0, %rax
jnz .loop
Run Code Online (Sandbox Code Playgroud)

dec指令影响该ZF标志(如同cmp),因此如果递减rax结果为零,ZF则将被设置.您可以利用这一事实并jnz直接放置dec.你根本不需要cmp:

decq %rax
jnz .loop
Run Code Online (Sandbox Code Playgroud)


Jon*_*art 7

cmpq $0, (%rax)
Run Code Online (Sandbox Code Playgroud)

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

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

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

cmpq $0, %rax
Run Code Online (Sandbox Code Playgroud)

  • 观察是cmpq可以完全消除. (2认同)