Как инициализировать локальную структуру в сборке MASM - PullRequest
0 голосов
/ 08 июня 2019

Я хочу инициализировать локальную структуру в стеке.

Records         STRUCT
data1           DWORD   ?
data2           DWORD   ?
data3           DWORD   ?
data4           DWORD   ?
Records         ENDS

                .CODE
main:
                mov     ebp, esp
                sub     esp, SIZEOF Records

Как создать именованный экземпляр структуры Records, который затем я могу использовать для инициализации членов данных.Я хочу использовать директиву struct с оператором точки, а не с добавлением указателя.

Я начал с выделения места для структуры.Тогда что?

1 Ответ

3 голосов
/ 08 июня 2019

Я бы использовал силу директивы PROC для определения функций 1 и директивы LOCAL для распределения переменных в функции.Ассемблер будет иметь дело с кодом пролога и эпилога, и вы можете связать тип с локальным.

Вы можете написать функцию, которая выглядит следующим образом:

main PROC
    LOCAL rec1: Records
    mov rec1.data1, 1
    mov rec1.data2, 2
    mov rec1.data3, 3
    mov rec1.data4, 4

    ret
main ENDP

Код будет выделять пространство настек для переменной с именем rec1, а остальные строки инициализируют поля структуры значениями 1,2,3,4.Сгенерированный ассемблерный код будет выглядеть примерно так:

Segment: _TEXT DWORD USE32 00000033 bytes
0000                            _main:
0000  55                                push            ebp
0001  8B EC                             mov             ebp,esp
0003  83 EC 10                          sub             esp,0x00000010
0006  C7 45 F0 01 00 00 00              mov             dword ptr -0x10[ebp],0x00000001
000D  C7 45 F4 02 00 00 00              mov             dword ptr -0xc[ebp],0x00000002
0014  C7 45 F8 03 00 00 00              mov             dword ptr -0x8[ebp],0x00000003
001B  C7 45 FC 04 00 00 00              mov             dword ptr -0x4[ebp],0x00000004
0022  C9                                leave
0023  C3                                ret

Ассемблер создал кадр стека и рассчитал для вас все смещения в стеке относительно EBP .Если вы хотите получить адрес rec1 в регистр и работать с ним как со структурой, вы можете использовать LEA, чтобы получить эффективный адрес переменной в стеке, и использовать ASSUME, чтобы применить к ней тип указателя.:

main PROC
    LOCAL rec1: Records
    lea eax, [rec1]
    ASSUME eax: ptr Records
    mov [eax].data1, 1
    mov [eax].data2, 2
    mov [eax].data3, 3
    mov [eax].data4, 4
    ret
main ENDP

Сгенерированный код сборки будет:

Segment: _TEXT DWORD USE32 00000035 bytes
0000                            _main:
0000  55                                push            ebp
0001  8B EC                             mov             ebp,esp
0003  83 EC 10                          sub             esp,0x00000010
0006  8D 45 F0                          lea             eax,-0x10[ebp]
0009  C7 00 01 00 00 00                 mov             dword ptr [eax],0x00000001
000F  C7 40 04 02 00 00 00              mov             dword ptr 0x4[eax],0x00000002
0016  C7 40 08 03 00 00 00              mov             dword ptr 0x8[eax],0x00000003
001D  C7 40 0C 04 00 00 00              mov             dword ptr 0xc[eax],0x00000004
0024  C9                                leave
0025  C3                                ret

Вы также можете использовать директиву LOCAL для создания массива типов.Затем вы можете инициализировать элементы отдельных записей в массиве.В этом примере выделяется место в стеке для массива 4 Records, называемого rec1, и инициализируется третий элемент (индекс массива 2, поскольку нумерация элементов массива начинается с нуля):

main PROC
    LOCAL rec1[4]: Records
    ; Compute address of third Record structure in array
    lea eax, [rec1]
    ASSUME eax: ptr Records
    add eax, 2*(SIZEOF Records)
    ; Initialize the the third Record structure
    mov [eax].data1, 1
    mov [eax].data2, 2
    mov [eax].data3, 3
    mov [eax].data4, 4
    ret
main ENDP

Сгенерированная сборкакод будет:

Segment: _TEXT DWORD USE32 00000038 bytes
0000                            _main:
0000  55                                push            ebp
0001  8B EC                             mov             ebp,esp
0003  83 EC 40                          sub             esp,0x00000040
0006  8D 45 C0                          lea             eax,-0x40[ebp]
0009  83 C0 20                          add             eax,0x00000020
000C  C7 00 01 00 00 00                 mov             dword ptr [eax],0x00000001
0012  C7 40 04 02 00 00 00              mov             dword ptr 0x4[eax],0x00000002
0019  C7 40 08 03 00 00 00              mov             dword ptr 0x8[eax],0x00000003
0020  C7 40 0C 04 00 00 00              mov             dword ptr 0xc[eax],0x00000004
0027  C9                                leave
0028  C3                                ret

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

    lea eax, [rec1 + 2*(SIZEOF Records)]
    ASSUME eax: ptr Records

Структуры в глобальной области действия

Если вы создаете структуры в глобальной области действия (не локальные в стеке), вы можете объявить и инициализировать ихтаким образом:

                .DATA
rec2 Records <1,2,3,4>

Каждое поле в структуре разделено запятой.Структура будет выглядеть в сегменте _DATA следующим образом:

Segment: _DATA DWORD USE32 00000010 bytes
0000  01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 ................

Данные печатаются в байтах.Каждый отдельный DWORD отображается с LSB (младший байт) до MSB (старший значащий байт).Если они отображаются как DWORD, они будут отображаться как

0000 00000001 00000002 00000003 00000004

Сноски

  • 1 Я использовал *Директива 1072 * в верхней части файла сборки для принятия соглашения о вызовах в стиле C по умолчанию:

    .386
    .model flat, C
    
...