在 X86 程序集中访问和移动字节

Posted

技术标签:

【中文标题】在 X86 程序集中访问和移动字节【英文标题】:Accessing and moving bytes in X86 assembly 【发布时间】:2015-12-17 11:08:22 【问题描述】:

我有几个关于 X86 汇编中的内存和寄存器的问题:

    我有一个字符串"abcdefgh",而寄存器%eax 拥有一个指向该字符串的指针。现在我使用movl (%eax), %edx 将字符串的前四个字节抓取到%edx 中。它们是如何存储在寄存器中的?是%dl寄存器中的字符d,还是字符a

    例如,当使用movb %eax, %dl 时,它实际上移动了%eax 的哪些字节? %al 中的那个还是相反的那个?甚至有可能做到这一点吗?或者我应该使用这样的指针 - movb (%eax), %dh - 来获取指针指向的第一个字节?

【问题讨论】:

如果要复制%eax的低字节,请使用mov %al, %dl。要移动第二个字节,请使用mov %ah, %dl。要获取其他两个字节之一,请复制/移位/屏蔽,或使用 BMI1 bextr。要扩展,请使用 movsx / movzx 进行符号/零扩展,如 movsx %al, %edx。或movsxbl (%eax), %edx 对内存中的一个字节进行符号扩展,由%eax 指向。见***.com/questions/34058101/… 与此相关,但使用 Intel 语法。 等等,假设 EAX 指向字符串"abcd",使用movb (%eax), %cl 是否将ad 移动到%cl m0skit0 的回答是正确的:从指向字符串开头的指针加载字节将加载第一个字节:'a' 更有趣的是从同一地址加载 32b 到 @987654348 @ 仍会将'a' 加载到%cl 中,这与您在大端机器上得到的相反。我的评论是对您问题的寄存器-寄存器移动部分的回应,您可以在其中复制 %eax 的一个字节,而不是取消引用它。 最后一个问题:我可以使用cmpb %bl, (%eax) 来比较%bl 中的字节和%eax 指向的第一个字节吗? 是的,当然。 cmp 可以将内存操作数作为第一个或第二个操作数。另请注意,您只需要大小后缀不明确的情况(例如立即数和内存操作数,如 cmpb $0xab, (%eax)cmpl $0xab, (%eax))。 【参考方案1】:

假设您使用的是不寻常的 GAS 语法(源是第一个操作数,目标​​是第二个操作数)而不是英特尔的:

它们是如何存储在寄存器中的? %dl 中的字符 d 注册,还是字符a?

由于您像访问 32 位数字一样访问字符串,因此适用字节序。 x86 是 little-endian,因此您在最低地址获得最低有效字节,因此 DL 将保存“a”(0x61),整个 EDX 将是 0x64636261。

例如,当使用 movb %eax, %dl 时,%eax 的哪个字节会执行此操作 实际移动? %al 中的那个还是相反的那个?有没有可能 这样做?

这会产生语法错误,因为操作数的大小不同。您不能将 32 位移动到 8 位。

或者我应该使用这样的指针 - movb (%eax), %dh - 来获取 指针指向的第一个字节?

如果您想访问 EAX 指向的数据而不是 EAX 本身,那么是的,应该可以。

【讨论】:

以上是关于在 X86 程序集中访问和移动字节的主要内容,如果未能解决你的问题,请参考以下文章

如何在 x86 程序集中移动两个浮点数的 mul 的结果?

在x86程序集中写入.bss部分

在 x86 程序集中打印十六进制值

错误 C2403 使用内联 x86 C++ 程序集将寄存器内容移动到变量

无法访问另一个程序集中的公共类型成员。我有两个程序集,我想从另一个程序集中的一个程序集访问公共成员

在 MASM 程序集中逐字节循环和处理字符串