2017-10-08 386 views
0

enter image description here

这是从我的腿上弹问题的汇编代码,我陷在阶段2; 炸弹实验室要求我们根据汇编代码找出正确的输入,否则会爆炸。

从< +20>我知道%rbp -0x30(48)== 0或者它会调用< +32>并炸开炸弹;因此%rbp = 48(DEC)

之后(+26)%rbp - 0x2c(44)必须等于1或它会爆炸炸弹... 但是由于%rbp = 48,炸弹会爆炸到任何地方所以我现在迷惑......

我想我误解了并发症,JE/JNE或如何计算这些东西......

+0

通过进入“read_six_numbers”我知道输入是6个数字,并且有一些模式 – James

+2

Do不张贴文字的图片。从终端复制/粘贴。 –

+1

[请勿放置文字图像](https://meta.stackoverflow.com/q/303812/995714) –

回答

1

-0x30(%ebp)并不意味着要使用的值%ebp - 0x30。这是一个内存地址来读取。该指令(cmpl)的后缀为l,所以它处理的是4字节的数量。所以实际发生的是它从地址%ebp - 0x30中读取一个4字节的数字并检查它是否为零。

(该$前缀意味着它是一个直接的价值,而不是一个地址。这就是为什么0x0是从字面上,而不是取消引用。)

+0

非常感谢!但是现在我怎么才能知道%ebp的价值是什么,因为它直接读取4字节内存。我对此一无所知。 – James

+0

@James好吧,假设代码在调用'read_six_numbers'之前将'%ebp-0x30'的地址加载到'%rsi'(第一个参数)中,我认为这是'read_six_numbers'放置结果的地方;即它是6个整数的缓冲区的开始。这与48 = 6 \ * 8的大小(对于6个8字节整数)是一致的......除非这样做没有意义,因为我们只比较4个字节的整数。嗯... – melpomene

+0

它是'%rbp',而不是'%ebp'。这是一个64位指针(对4个字节的内存)。它在这个函数中被用作帧指针,所以它的高32位不全是零,'0x30(%ebp)'会出现段错误。 –

1

你不需要知道的rbp值拆除炸弹的引信,它的总是用相对的方式来处理某些内存部分。它设置在启动由序列:

pushq %rbp 
    movq %rsp, %rbp 
    pushq %r12 
    pushq %rbx 
    subq $0x20, %rsp 

这确实推动老rbp值到栈(保存它),然后将rbp到当前堆栈指针值(rsp)。所以(%rbp)现在包含旧的rbp。然后通过将另外两个寄存器r12rbx推入堆栈(现在生成rsp == rbp - 16)来保存它们。然后rsp再次被减去32,即rsp == rbp - 48

这是常见的模式,如何为局部变量分配内存空间,即任何进一步的push指令都将使用低于rbp - 48的内存。内存从rbp - 48rbp - 17(增量)未定义,可以自由用作“局部变量”内存。然后在rbp - 16存储8字节原始rbx值,在rbp - 8存储原始r12值,并在rbp存储旧rbp。 (我的意思是所有的“rbp-x”被用作内存地址来存储内存中的值)

然后你的代码调用输入6个数字,我猜的意思是32位整数(由下面的代码判断),所以它提供了地址为rbp - 48。 6 * 4 = 24 =>输入值将存储在地址rbp - 48直到(含)rbp - 25的存储器中。

注“未使用的内存”从rbp - 24高达rbp - 17的差距,这是另一个8个字节的备用本地存储,不使用你发布的代码,这是由编译器中加入极有可能的留白,使rspcallq read_six_numbers之前正确对齐。

所以基本上你不需要知道哪儿rsp/rbp点,它指向一些有效的堆栈存储器(可能是,或代码将崩溃,而炸弹将爆炸......有点怪设计:))))。您可以在开始时选取任意值,如0x8000rsp),然后用此模拟运行。 (即<+11> leaq -0x30,(%rbp), %rsi然后rsi = 0x7FC8;(为0x8000 - 8 - 的0x30)

什么-x(%rbp)意味着各种指令(要注意的“内存操作数”使用的lea VS <any other instruction>语义差别休息时,lea确实只有内存地址计算,而其他指令只是以此为起点,使用计算得到的地址访问存储在内存中的实际值)在其他答案+注释中进行了描述,并使用x86指令参考指南并通过一些教程再次阅读,直到它