使用 IA32 或 x86 在 C 中访问联合
Accessing unions in C using IA32 or x86
如果我有一个这样声明的联合:
union u1 {
struct s1 *h;
struct s2 *i;
char j;
};
如何使用 IA32 或任何程序集访问第一个、第二个或第三个元素?
如果我理解联合是正确的,这个联合的字节顺序应该只占用 4 个字节 (IA32),因为 IA32 中的指针是 4 个字节。
联合体的所有成员共享初始地址,所以无论你想读取联合体的哪个成员,它在内存中的相同位置,你唯一需要改变的是如何解释它。
如果您有 u1
实例的地址,例如 eax
,您可以获得 h
或 i
的值(即地址h
或 i
指向),例如 ebx
,通过一个微不足道的
mov ebx, dword ptr[eax]
(两者相同,因为在汇编中不同指针类型之间没有真正的区别)
至于在 bl
中阅读 j
,那就是
mov bl, byte ptr[eax]
Edit:正如 Peter Cordes 所说的那样,如果你真的想用它做全寄存器运算,这就是在 C 中的数学表达式中使用它时会发生这种情况,如果您的 char
已签名,则需要对其进行符号扩展,通常是:
movsx ebx, byte ptr[ebx]
或零扩展,如果它是 unsigned
:
mobzx ebx, byte ptr[ebx]
对于x86_64,本质上是一样的,只是改变了一些register/memory操作数的大小:
mov rbx, qword ptr[rax]
或
mov bl, byte ptr[rax]
如果我有一个这样声明的联合:
union u1 {
struct s1 *h;
struct s2 *i;
char j;
};
如何使用 IA32 或任何程序集访问第一个、第二个或第三个元素? 如果我理解联合是正确的,这个联合的字节顺序应该只占用 4 个字节 (IA32),因为 IA32 中的指针是 4 个字节。
联合体的所有成员共享初始地址,所以无论你想读取联合体的哪个成员,它在内存中的相同位置,你唯一需要改变的是如何解释它。
如果您有 u1
实例的地址,例如 eax
,您可以获得 h
或 i
的值(即地址h
或 i
指向),例如 ebx
,通过一个微不足道的
mov ebx, dword ptr[eax]
(两者相同,因为在汇编中不同指针类型之间没有真正的区别)
至于在 bl
中阅读 j
,那就是
mov bl, byte ptr[eax]
Edit:正如 Peter Cordes 所说的那样,如果你真的想用它做全寄存器运算,这就是在 C 中的数学表达式中使用它时会发生这种情况,如果您的 char
已签名,则需要对其进行符号扩展,通常是:
movsx ebx, byte ptr[ebx]
或零扩展,如果它是 unsigned
:
mobzx ebx, byte ptr[ebx]
对于x86_64,本质上是一样的,只是改变了一些register/memory操作数的大小:
mov rbx, qword ptr[rax]
或
mov bl, byte ptr[rax]