我知道我可以jump
用来将程序计数器设置为一个特定的行,所以我可以跳过一行或多行(或再次执行一些行).我可以轻松地跳过下一行而无需输入行号吗?
在运行时"注释掉"某些内容非常方便.
我的任务是表达一些看似奇怪的C代码行为(在x86上运行).我可以很容易地完成其他所有事情,但这个让我很困惑.
代码段1输出
-2147483648
Run Code Online (Sandbox Code Playgroud)int a = 0x80000000; int b = a / -1; printf("%d\n", b);
代码片段2没有输出任何内容,并给出了一个
Floating point exception
Run Code Online (Sandbox Code Playgroud)int a = 0x80000000; int b = -1; int c = a / b; printf("%d\n", c);
我很清楚Code Snippet 1(1 + ~INT_MIN == INT_MIN
)的结果的原因,但是我不太明白整数除以-1如何生成FPE,也不能在我的Android手机(AArch64,GCC 7.2.0)上重现它.代码2只输出与代码1相同,没有任何例外.它是x86处理器的隐藏bug功能吗?
该任务没有告诉任何其他内容(包括CPU架构),但由于整个课程基于桌面Linux发行版,您可以放心地认为它是一个现代的x86.
编辑:我联系了我的朋友,他在Ubuntu 16.04(Intel Kaby Lake,GCC 6.3.0)上测试了代码.结果与所指定的任何内容一致(代码1输出所述内容,代码2与FPE崩溃).
我在llvm clang Apple LLVM 8.0.0版(clang-800.0.42.1)上反汇编代码:
int main() {
float a=0.151234;
float b=0.2;
float c=a+b;
printf("%f", c);
}
Run Code Online (Sandbox Code Playgroud)
我编译时没有-O规范,但我也试过-O0(给出相同)和-O2(实际上计算值并存储它预先计算)
产生的反汇编如下(我删除了不相关的部分)
-> 0x100000f30 <+0>: pushq %rbp
0x100000f31 <+1>: movq %rsp, %rbp
0x100000f34 <+4>: subq $0x10, %rsp
0x100000f38 <+8>: leaq 0x6d(%rip), %rdi
0x100000f3f <+15>: movss 0x5d(%rip), %xmm0
0x100000f47 <+23>: movss 0x59(%rip), %xmm1
0x100000f4f <+31>: movss %xmm1, -0x4(%rbp)
0x100000f54 <+36>: movss %xmm0, -0x8(%rbp)
0x100000f59 <+41>: movss -0x4(%rbp), %xmm0
0x100000f5e <+46>: addss -0x8(%rbp), %xmm0
0x100000f63 <+51>: movss %xmm0, -0xc(%rbp)
...
Run Code Online (Sandbox Code Playgroud)
显然它正在做以下事情:
asm()
在未使用但不受支持的架构中,代码块的行为是什么?例如,如果我在ARM上编译以下代码会发生什么
if (false) {
asm volatile("x86specificinstruction" ...);
}
Run Code Online (Sandbox Code Playgroud)
这是有效的C++吗?代码会编译吗?标准是否对此类情况有所说明?
这是用于64位x86 Intel处理器的。
在GDB中,我可以看到:
0x400500 <main+50>: call 0x400100 <somefunc>
Run Code Online (Sandbox Code Playgroud)
但是,当我检查0x400500处的内存时,看不到对“ 0x400100”的任何引用,附近的寄存器中也没有任何明显的内容。
如何“知道”在哪里打电话。看起来很简单,但我一直找不到答案。
我试图用例如上述函数的参数调用系统,但只有有限的内存访问权限。请注意,这只是出于娱乐目的,是挑战练习的一部分。