汇编中结构参数的字段是如何排序的?

How fields of strucure arguments in assembly are ordered?

我有一个 excel 脚本,它从 DLL 文件调用一个函数。我已经打开了 DLL 文件,但我对它的了解不多。

excel脚本定义了以下结构:

Public Type Product
    price As Double
    size As Double
    isExpensive As Boolean
    isCheap As Boolean
    isVerified As Boolean
    isPacked As Boolean
    isDelivered As Boolean
End Type

Public Type Pricing
    value1 As Double
    value2 As Double
    value3 As Double
    value4 As Double
End Type

Public Type Receipt
    price As Double
    location_x As Double
    location_y As Double
    time As Double
    gross_weight As Double
    special_weight As Double
    discount As Double
    dispatched As Boolean
    paid As Boolean
End Type

Public Type Location
    reputation As Double
    id As Long
    staffs As Long
    location_x As Double
    location_y As Double
    working_weekends As Boolean
    ventilated As Boolean
End Type

Public Type Output
    future_week1 As Double
    future_week2 As Double
    future_week3 As Double
    future_week4 As Double
    future_week5 As Double
    future_week6 As Double
    future_week7 As Double
    future_week8 As Double
    future_week9 As Double
    future_week10 As Double
    future_week11 As Double
    future_week12 As Double
    future_week13 As Double
    future_week14 As Double
    future_week15 As Double
    future_week16 As Double
    future_week17 As Double
    future_week18 As Double
End Type

并调用以下函数

EstimateFuture myProduct, pricing1, pricing2, receipt1, location, myoutput

此函数接收 myProductpricing1pricing2receipt1location 作为输入,并将输出放入 myoutput .

不管这些结构设计得好不好。我需要了解每个字段在内存中的顺序。

估算函数的汇编开头如下:

EstimateFuture:
    push    ebp
    mov ebp,esp
    and esp,FFFFFFF8h
    sub esp,000000A0h
    push    esi
    mov esi,[ebp+08h]
    push    edi
    mov ecx,0000000Ch
    mov edi,L1000F198
    rep movsd
    mov esi,[ebp+0Ch]
    mov ecx,00000008h
    mov edi,L1000F250
    rep movsd
    mov esi,[ebp+10h]
    mov ecx,00000008h
    mov edi,L1000F208
    rep movsd
    mov esi,[ebp+14h]
    mov ecx,00000010h
    mov edi,L1000F1C8
    rep movsd
    mov esi,[ebp+18h]
    mov ecx,0000000Ah
    mov edi,L1000F228
    rep movsd
    ...

显然上面的代码试图将参数存储到它的内存中。这里我们有六个参数和五个 rep movsd。可能是因为输入了五个变量而最后一个没有。

但我不明白的是,地址与变量完全不匹配。既不是根据它们的大小,也不是根据它们的标签分割。无论参数是以直接方式还是反向方式存储,它们都与以下地址不匹配:

L1000F198:
        dq  0000000000000000h
L1000F1A0:
        dq  0000000000000000h
L1000F1A8:
        db  00h;
        db  00h;
        db  00h;
        db  00h;
L1000F1AC:
        db  00h;
        db  00h;
L1000F1AE:
        db  00h;
        db  00h;
        db  00h;
        db  00h;
L1000F1B2:
        db  00h;
        db  00h;
L1000F1B4:
        db  00h;
        db  00h;
        db  00h;
        db  00h;
L1000F1B8:
        dq  0000000000000000h
L1000F1C0:
        dq  0000000000000000h
L1000F1C8:
        dq  0000000000000000h
L1000F1D0:
        dq  0000000000000000h
L1000F1D8:
        dq  0000000000000000h
L1000F1E0:
        dq  0000000000000000h
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
L1000F1F0:
        dq  0000000000000000h
L1000F1F8:
        dq  0000000000000000h
L1000F200:
        db  00h;
        db  00h;
L1000F202:
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
L1000F208:
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
L1000F210:
        dq  0000000000000000h
L1000F218:
        dq  0000000000000000h
L1000F220:
        dq  0000000000000000h
L1000F228:
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
L1000F230:
        dd  00000000h
L1000F234:
        dd  00000000h
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
L1000F240:
        dq  0000000000000000h
L1000F248:
        db  00h;
        db  00h;
L1000F24A:
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
L1000F250:
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
L1000F258:
        dq  0000000000000000h
L1000F260:
        dq  0000000000000000h
L1000F268:
        dq  0000000000000000h
L1000F270:
        dd  00000000h
L1000F274:
        db  00h;
        db  00h;
        db  00h;
        db  00h;
L1000F278:
        dd  00000000h
L1000F27C:
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
L1000F284:
        dd  00000000h
L1000F288:
        dd  00000000h
        db  00h;
        db  00h;
        db  00h;
        db  00h;
L1000F290:
        dd  00000000h
L1000F294:
        db  00h;
        db  00h;
        db  00h;
        db  00h;
L1000F298:
        db  00h;
        db  00h;
        db  00h;
        db  00h;

我不知道这个 DLL 文件的原始语言,也不知道编译器的名称或版本。

有人可以帮我填一下这个谜题吗?

address of myProduct.price = ?
address of myProduct.size = ?
address of myProduct.isExpensive = ?
address of myProduct.isCheap = ?
address of myProduct.isVerified = ?
address of myProduct.isPacked = ?
address of myProduct.isDelivered = ?

address of pricing1.value1 = ?
address of pricing1.value2 = ?
address of pricing1.value3 = ?
address of pricing1.value4 = ?

address of pricing2.value1 = ?
address of pricing2.value2 = ?
address of pricing2.value3 = ?
address of pricing2.value4 = ?

address of receipt1.price = ?
address of receipt1.location_x = ?
address of receipt1.location_y = ?
address of receipt1.time = ?
address of receipt1.gross_weight = ?
address of receipt1.special_weight = ?
address of receipt1.discount = ?
address of receipt1.dispatched = ?
address of receipt1.paid = ?


address of location.reputation = ?
address of location.id = ?
address of location.staffs = ?
address of location.location_x = ?
address of location.location_y = ?
address of location.working_weekends = ?
address of location.ventilated = ?

address of myoutput.future_week1 = ?
address of myoutput.future_week2 = ?
address of myoutput.future_week3 = ?
address of myoutput.future_week4 = ?
address of myoutput.future_week5 = ?
address of myoutput.future_week6 = ?
address of myoutput.future_week7 = ?
address of myoutput.future_week8 = ?
address of myoutput.future_week9 = ?
address of myoutput.future_week10 = ?
address of myoutput.future_week11 = ?
address of myoutput.future_week12 = ?
address of myoutput.future_week13 = ?
address of myoutput.future_week14 = ?
address of myoutput.future_week15 = ?
address of myoutput.future_week16 = ?
address of myoutput.future_week17 = ?

更新

感谢matan7890,现在我知道myProduct的地址在L1000F228:

L1000F228:
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
L1000F230:
        dd  00000000h
L1000F234:
        dd  00000000h
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
L1000F240:
        dq  0000000000000000h
L1000F248:
        db  00h;
        db  00h;
L1000F24A:
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;
        db  00h;

意思是:

address of myProduct.price = L1000F228 (8 bytes)
address of myProduct.size = L1000F230 (8 bytes)
address of myProduct.isExpensive = L1000F238 (4 bytes) -----> No Label
address of myProduct.isCheap = L1000F23C (4 bytes) -----> No Label
address of myProduct.isVerified = L1000F240 (4 bytes)
address of myProduct.isPacked = L1000F244 (4 bytes) -----> No Label
address of myProduct.isDelivered = L1000F248 (4 bytes)

这里,问题是 myProduct.isExpensivemyProduct.isCheapmyProduct.isPacked 的开头没有标签。

其他问题是

myProduct.price 由 8 个单字节组成,而不是单个 8 个字节。

myProduct.size 必须是 8 个字节,但在 4 个字节之后引入另一个标签。

标签似乎没有放在正确的位置。

首先,请注意您传递的参数的顺序与您在堆栈中的想法相反。例如,您的第一个变量 myProduct[ebp+18h] 中。

此外,请注意 vb Boolean 是 4 个字节而不是 1 个字节。因此,您的产品类型是 36 个字节,Pricing 是 32 个字节,依此类推。 movsd 操作码一次复制 4 个字节(双字)。通过阅读 reps,您的参数似乎顺序不正确,因为第二个参数复制 64 个字节(4 * 10h == 4 * 16 = 64),就像您的 Receipt 类型.似乎参数的正确顺序,仅通过参考所需的大小,是:

EstimateFuture myProduct, receipt1, pricing1, pricing2, location, myoutput

这意味着 myProduct 似乎在 L1000F228 和接下来的 40 个字节中。请注意,您的结构只有 36 个字节,这意味着您可能缺少该类型中的一个 Boolean 成员。

从这里你可以自己计算:)