【问题标题】:Cutting QWORD to get DWORD and performing calculations upon it切割 QWORD 以获得 DWORD 并对其执行计算
【发布时间】:2017-10-16 13:10:57
【问题描述】:
mov  rax,QWORD PTR [rbp-0x10]

mov  eax,DWORD PTR [rax]

add  eax,0x1

mov  DWORD PTR [rbp-0x14], eax

下一行用 C 编写,在 GNU/Linux 环境中使用 GCC 编译。

汇编代码用于 int b = *a + 1;.

...

int a = 5;

int* ptr = &a;

int b = *a + 1;

取消引用 a 地址中的内容并将其加 1。之后,存储在新变量下。

我不明白汇编代码中的第二行。这是否意味着我将 QWORD 剪切为 DWORD(QWORD 的一部分)并将其存储到 eax 中?

由于代码只有几行,我很乐意将其分成几部分,以确认我在正确的轨道上,同时弄清楚第二行的作用。谢谢。

【问题讨论】:

  • 您发布的程序集只是一个片段。例如,将a 初始化为5 的指令丢失。如果你可以发布整个函数,解释可能会更容易产生。
  • int* 在 x64 代码中是 8 个字节,因此是 QWORD。取消引用指针会在 x64 代码中产生 int,4 个字节,因此是 DWORD。
  • @HansPassant 我相信这个答案可以满足我的需求。非常感谢。
  • int b = *a + 1; 行如何编译?表达式 *a 无效,因为 a 的类型为 int。你打错字了吗,应该改成int b = *ptr + 1;吗?

标签: c assembly compilation


【解决方案1】:

我不明白的是该汇编代码中的第二行。这是否意味着我将 QWORD 剪切为 DWORD(QWORD 的一部分)并将其存储到 eax 中?

不,第二行取消引用它。没有将 qword 分成两个 dword 半。 (Writing EAX zeros the upper 32 bits of RAX)。

它只是碰巧使用了与指针相同的寄存器,因为它不再需要指针了。

在启用优化的情况下编译;如果 gcc 没有一直存储/重新加载,则更容易看到发生了什么。 (How to remove "noise" from GCC/clang assembly output?)

int foo(int *ptr) {
    return *ptr + 1;
}

    mov     eax, DWORD PTR [rdi]
    add     eax, 1
    ret

(On Godbolt)

【讨论】:

  • 谢谢,但我正在寻找上面这些行的解释。
  • 你回答错了问题。他想取消引用从整数值转换而来的指针
  • @PeterJ_01 我认为他在回答正确的问题,但这有点令人困惑,因为在发布的 C 代码中根本没有 dereference (事实上,它不会编译) - 但在 asm 中有明显的尊重。也没有选角,不知道你在看什么?
  • @BeeOnRope:呵呵,我只是想回答一下“切”一个qword的粗体问题,没有仔细看C。我含蓄地假设你在这个问题上指出了什么,OP 的意思是*ptr 而不是*a。更新了我的示例以使用 ptr 作为变量名!
【解决方案2】:
int a = 5;

int* ptr = &a;

int b = *a + 1;

您的示例是一个未定义的行为,因为您取消引用转换为指针的整数值(在本例中为 5)并且它根本不会编译,因为此转换具有未知类型。

要使其正常工作,您需要先进行投射。 `int b = *(int *)a + 1;

https://godbolt.org/g/Yo8dd1

您的汇编代码说明:

第 1 行:使用 a 的值加载 rax(在本例中为 5) 第 2 行:取消引用该值(从地址 5 读取,因此您可能会遇到分段错误)。此代码从堆栈加载只是因为您使用了 -O0 选项。

【讨论】:

    猜你喜欢
    • 2016-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多