【问题标题】:Understanding of the following assembly code from CSAPP从CSAPP理解以下汇编代码
【发布时间】:2017-10-30 21:41:00
【问题描述】:

我最近正在阅读 CSAPP,并且对汇编代码示例有疑问。这是一个来自 CSAPP 的例子,代码如下:

    long pcount_goto
    (unsigned long x) {
    long result = 0;
    result += x & 0x1;
    x >>= 1;
    if(x) goto loop;
    return result;

 而对应的汇编代码为:

   movl    $0, %eax     #  result = 0
   .L2:                 # loop:
    movq    %rdi, %rdx
    andl    $1, %edx    #  t = x & 0x1
    addq    %rdx, %rax   #  result += t
    shrq    %rdi         #  x >>= 1
    jne .L2                 #  if (x) goto loop
    rep; ret

我的问题可能看起来很幼稚,因为我对汇编代码很陌生,但如果有人能帮助我解决这些问题,我将不胜感激。

  1. %eax、%rax(还有 %edx、%rdx)有什么区别。我已经看到它们出现在汇编代码中,但它们似乎指的是相同的空间/地址。使用两个不同的名称有什么意义?

  2. 在代码中

    andl    $1, %edx    #  t = x & 0x1
    

    我知道 %edx 现在存储 t,但是 x 到哪里去呢?

  3. 在代码中

    shrq    %rdi  
    

    我觉得

     shrq   1, %rdi
    

    应该更好吗?

  4. 对于

    jne .L2                 #  if (x) goto loop
    

    如果 (x) 去哪里了?我看不到任何判断。

【问题讨论】:

  • 源缺少loop: 标签(尽管不难想象它属于哪里)。如果您对 edxrdx 的区别感到困惑,那么在 Jester 回答之后,您应该会说“啊哈,但如果 and 只屏蔽 32b,为什么 add 使用 64b”...答案是,当使用e 变体时,x86-64 将清除寄存器的高位 32b,因此andl $1,%edxandq $1,%rdx 具有相同的结果,但机器码短了 1 个字节。

标签: c++ c assembly


【解决方案1】:

这些都是非常基本的问题,您自己的一点研究应该可以回答所有这些问题。总之,

  1. e 寄存器是r 寄存器的低 32 位。您可以根据需要的尺寸选择一种。还有 16 位和 8 位寄存器。请查阅基本架构手册。
  2. and 指令修改了它的参数,不是a = b & c,而是a &= b
  3. shrq $1, %rdi 是有效的,shrq %rdi 只是它的别名。
  4. 如果结果为零,jne 会自动检查 shrq 之前设置的零标志。

【讨论】:

  • 该课程没有包含太多细节。谢谢解答!
  • @LAWRENCE 对于特定指令,您可以先查看简短的参考指南,如x86.renejeschke.de,但对于寄存器等整体 x86 CPU 架构,可能需要搜索一些书籍或教程。总是有来自英特尔的官方文档可用,它只有几千页的 pdf(仍然查看内容表可能是值得的)。在互联网时代说“课程不包含太多细节”......很奇怪。虽然他们本可以给你一些推荐的文献。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-22
  • 1970-01-01
  • 2015-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多