说,我已经在Assembly中定义了一个结构。我怎么能这样做?
struct some_struct_t *s1 = (struct some_struct_t *)some_buffer;
,其中
char some_buffer[1024];
malloc = malloc(1024);
memset(some_buffer, 0, 1024);
我能想到lea或mov,但究竟是怎么回事?
答案 0 :(得分:3)
考虑这个C代码(具有实现定义的行为)
void foo()
{
struct struct1* s1 = (struct struct1*)0x01234567; /* exp1 */
struct struct2* s2 = (struct struct2*)0x01234567; /* exp2 */
struct struct3* s3 = (struct struct3*)0x01234567; /* exp3 */
float* f = (float*)0x01234567; /* exp4 */
int* i = (int*)0x01234567; /* exp5 */
char* c = (char*)0x01234567; /* exp6 */
}
为了清晰起见,假设s1
位于[rsp-08h]
,则 exp1 汇总为
mov QWORD [rsp-08h], 1234567h
为了清晰起见,假设s2
位于[rsp-10h]
,则 exp2 汇编为
mov QWORD [rsp-10h], 1234567h
为了清晰起见,假设s3
位于[rsp-18h]
,则 exp3 汇编为
mov QWORD [rsp-18h], 1234567h
为了清晰起见,假设f
位于[rsp-20h]
,则 exp4 汇总为
mov QWORD [rsp-20h], 1234567h
为了清晰起见,假设i
位于[rsp-28h]
,则 exp4 汇总为
组装中没有类型的东西,因此没有演员阵容
汇编中只有数据,这就是为什么我们发明了类型化的高级语言,不是if
,也不是for
,而是类型检查。
如果您想struct some_struct_t *s1 = (struct some_struct_t *)some_buffer;
,则转换为s1 = some_buffer
这只是一个价值观的分配。
现在,因为some_buffer
是一个具有自动存储功能的数组,所以它转换为"它位于堆栈上#34;在x86上,您可能想知道除了(人工)演员之外,struct some_struct_t *s1 = (struct some_struct_t *)some_buffer;
的语义到底是什么,正如您现在所知,它只在编译过程中存在。
You surely know that some_buffer
decay into a pointer to the first element,那么在翻译该指令时唯一要做的就是弄清楚第一个元素的地址。
好吧,我不能告诉你很多,因为我不知道你放置第一个项目的位置,但一般some_buffer
是在堆栈上所以这个,一旦调整,将会做
;Compute the address of the first element
lea rax, [rsp+...] ;or [rbp-...] if a frame pointer is available
;Store it in a local var
mov QWORD [rsp+...], rax ;As above, also you can use any other scratch reg
使用第一个省略号代替偏移量,相对于数组第一项的rsp
。
第二个用于代替s1
指针的偏移量。
live example see here 请注意,在该示例中,GCC在使用Red区域时过于热心,但我们可以原谅他,因为我必须禁用任何优化才能进行合理的反汇编。
如果您想知道如何为malloc
执行相同操作,那么,如果您仍然不想使用godbolt.org,那么解决方案就在这里
mov edi, 1024
call malloc
mov QWORD [rsp+...], rax