在 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
是否将a
或d
移动到%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 程序集中访问和移动字节的主要内容,如果未能解决你的问题,请参考以下文章
错误 C2403 使用内联 x86 C++ 程序集将寄存器内容移动到变量