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行,它不会出错.但当然程序不会终止.
所以基本上我的问题是我在这里做错了什么?
提前致谢.
以下说明:
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)
cmpq $0, (%rax)
Run Code Online (Sandbox Code Playgroud)
该指令将尝试读取地址中的内存rax.
rax将是第一次99.地址99未映射,因此您的程序会出现段错误.
您打算将值rax与0 进行比较,因此请删除括号.
cmpq $0, %rax
Run Code Online (Sandbox Code Playgroud)