gpt4 book ai didi

c - 尝试将 C 转换为汇编

转载 作者:行者123 更新时间:2023-11-30 15:01:17 26 4
gpt4 key购买 nike

我在 C 中有一个结构:

struct struct1 {
uint16_t a;
uint32_t b;
char * c;
struct struct2* d;
}

如何在 Nasm 中定义相同的结构?我试过这个:

struc struct1
.a resw
.b resdw
.c ???? ; what should be here?
.d ???? ; what should be here?
endstruc

我怎样才能做到这一点?

最佳答案

这是一些考试测试,还是现实世界的 C 结构?

在现实世界中,它可能会被填充以对齐其成员,因此 .b可能是 4 或 8(或更多,取决于填充的编译时设置),而不是 2。

当真正执行 C<->asm 时,请确保使用一些“填充/打包”编译指示或编译时开关来始终编译为 C 二进制文件中的相同结构(第一步)。

然后可能会手动填充/对齐,例如我会将“a”放在最后,将“c”和“d”放在开头。因此,内存中的顺序将是“c、d、b、a”(即使对于“打包”模式下的 64b 目标,我也会发现“足够”对齐,生成的偏移量将是 [0, 8, 16, 20] ,大小将是 22字节)(编辑:我会在末尾添加另一个 word 只是为了将其填充到 24B 大小,如果我知道我会在数组中使用其中的许多)。

最后什么是cd在内存中->指针。通过“nasm”一词的使用,我感觉到 x86 目标平台,通过“uint32_t”,我感觉到它不是 16b 实模式,因此它们是 32 位或 64 位(取决于您的目标平台)。 32 位为 4 个字节,64 位为 8 个字节。

<小时/>

顺便说一句,您始终可以编写一些简短的 C 源代码来练习对结构的访问,并检查编译器的输出。

例如我将其放入 http://godbolt.org/ :

#include <cstdint>

struct struct1 {
uint16_t a;
uint32_t b;
char * c;
void * d;
};

std::size_t testFunction(struct1 *in) {
std::size_t r = in->a;
r += in->b;
r += uintptr_t(in->c);
r += uintptr_t(in->d);
return r;
}

并得到了这个(clang 3.9.0 -O3 -m32 -std=c++11):

testFunction(struct1*):              # @testFunction(struct1*)
mov ecx, dword ptr [esp + 4] ; ecx = "in" pointer
movzx eax, word ptr [ecx] ; +0 for "a"
add eax, dword ptr [ecx + 4] ; +4 for "b"
add eax, dword ptr [ecx + 8] ; +8 for "c"
add eax, dword ptr [ecx + 12] ; +12 for "d"
ret ; size of struct is 16B

对于 64b 目标:

testFunction(struct1*):              # @testFunction(struct1*)
mov rax, qword ptr [rdi]
movzx ecx, ax
shr rax, 32
add rax, rcx
add rax, qword ptr [rdi + 8]
add rax, qword ptr [rdi + 16]
ret

偏移量现在为 0、4、8 和 16,大小为 24B。

64b 目标添加了“-fpack-struct=1”:

testFunction(struct1*):              # @testFunction(struct1*)
movzx ecx, word ptr [rdi]
mov eax, dword ptr [rdi + 2]
add rax, rcx
add rax, qword ptr [rdi + 6]
add rax, qword ptr [rdi + 14]
ret

偏移量为 0、2、6 和 14,大小为 22B(对成员 bcd 的未对齐访问会损害性能)。

例如,对于 0、4、8、16 情况(64b 对齐),您的 NASM 结构应该是:

struc struct1
.a resd 1
.b resd 1
.c resq 1
.d resq 1
endstruc
<小时/>

根据您的进一步评论...我认为您可能有点想念汇编中的“struc”是什么。这是一个噱头,它只是指定地址偏移量的另一种方式。上面的例子也可以写成:

struc struct1
.a resw 1
resw 1 ; padding to make "b" start at offset 4
.b resd 1
.c resq 1
.d resq 1
endstruc

现在你也有了“a”的“resw”。对于ASM来说没关系,代码只是符号.a的值。和.b很重要,这些值为 04在这两个例子中。如何保留 struc 内的空间并不重要。定义,只要您为特定“变量”指定正确的字节数及其填充,它就不会影响结果。

关于c - 尝试将 C 转换为汇编,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41529894/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com