2017-01-08 2 views
0

У меня есть структуры в C:Попытка преобразовать 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 

Как это сделать?

+0

'.c <размер указателя>', '.d ' (который будет зависеть от архитектуры). –

ответ

1

Является ли это экзаменационным экзаменом или C-структурой реального мира?

В реальном мире он может быть дополнен, чтобы выровнять его членов, так что .b может быть затем 4 или 8 (или больше, зависит от компиляции установки времени для заполнения), не 2.

При выполнении C < - > asm для реального, не забудьте использовать какой-то «padding/packing» прагма или компилятор времени для компиляции всегда в одну и ту же структуру структуры в C-файлах (первый шаг).

Тогда, возможно, вы можете наложить/выровнять вручную, например, я бы поставил «a» как последний и «c» и «d» в начале. Таким образом, порядок в памяти будет «c, d, b, a» (который я нашел бы «достаточно», выровненным даже для цели 64b в «упакованном» режиме, результирующие смещения будут [0, 8, 16, 20], а размер будет 22 байт) (править : и я добавлю еще word в конец, чтобы разместить его до размера 24B, если бы я знал, что буду использовать многие из них в массиве).

И наконец, что такое c и d в памяти -> указатели. При использовании слова «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; 
} 

И получил на это (лязг 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-структуры = 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 (и производительность пострадает от выровненным доступа к членам b , c и d).

Так, например, для 0, 4, 8, 16 случая (64b выровнены) Ваш NASM структура должна быть:

struc struct1 
    .a resd 1 
    .b resd 1 
    .c resq 1 
    .d resq 1 
endstruc 

Из ваших дальнейших комментариев ... Я думаю, что вы, возможно, своего рода пропустите, что такое «структура» в сборке.Это трюк, это просто другой способ указания смещений адресов. Приведенный выше пример можно назвать также:

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 

Теперь у вас есть «resw» для «a». Для ASM это не имеет значения, так как для кода важно только значение символов .a и .b, и эти значения являются 0 и 4 в обоих примерах. Неважно, как вы зарезервируете пространство внутри определения struc, оно не влияет на результат, если вы укажете правильное количество байтов для конкретной «переменной» + его заполнения.

+0

Как я могу определить ** ту же структуру в Nasm? ** – ako25

+0

Почему a и b одного размера? – ako25

+0

@ ako25 сначала вы должны знать, что такое структура ** **. Как вы можете видеть, это может сильно измениться в зависимости от того, как вы его скомпилируете (цель + упаковка). Затем просто зарезервируйте достаточное количество байтов, я добавил также пример «nasm», но это выглядит как тривиальная часть, проверьте http://www.nasm.us/doc/nasmdoc3.html для различных директив 'resX' и на самом деле вы можете делать только с 'resb' .. как' resb 8' для указателей. – Ped7g

Смежные вопросы