汇编 x86 MASM 中的十六进制数组

Array in Hexadecimal in Assembly x86 MASM

如果: (我相信寄存器彼此相邻......)

 A BYTE 0xB, 0d20, 0d10, 0d13, 0x0C
 B WORD 0d30, 0d40, 0d70, 0hB 
 D DWORD 0xB0, 0x200, 0x310, 0x400, 0x500, 0x600 

然后:

我认为这些就是答案,但我不确定。由于一个 WORD 是 1 个字节,而 DWORD 是 2 个字,因此当您计算 [B+2] 的数组时,您应该从 0d30 开始,然后是 0d40(计算两个字)。 [A+2] 是 0d20 因为你在计算两个字节。我究竟做错了什么?请帮忙。谢谢

编辑

是不是因为:考虑到 A、B 和 D 的第一个值是偏移量 x86 是小端...A = 0d10,从那里再算 2 B...字节(十进制) ) = 30,0,40,0,70,0,11,0 B 是 0d40,从 D 中算出 2 个字节...字节(十六进制)= 0x200, 0,0,0,...0, 2,0,0,...0x10,3,0,0,...0,4,0,0,...0,5,0,0,...0,6,‌ 0, 0 D 是 0x200。从那里数 4 个字节。从 0xb0 向后数 10 个字节。那么 [D-10] 不等于 0x0C 吗?谢谢

另外如果我做[B-3],会是0d13吗?有人告诉我它实际上在 0d10 和 0d13 之间,因此它将是 0A0D,并且由于小端字节序将是 0D0A。那是对的吗?谢谢!! 编辑

WORD 是 2 个 BYTE。 DWORD 是两个 WORD("D" 代表 "double")。 QWORD 是 4*WORD (Quad).

内存 以字节为单位寻址,即。内存内容可以看作(对于三个字节,其值为:0xB、20、10):

address | value
----------------
0000    | 0B
0001    | 14
0002    | 0A

WORD 在内存中占用两个字节,在 x86 上,最低有效字节在低地址,最高有效字节在高地址。

所以 WORD 0x1234 存储在地址 0xDEAD 的内存中为:

address | value
----------------
DEAD    | 34
DEAE    | 12

x86 上的寄存器是直接位于 CPU 本身的特殊微小内存位,无法通过上述数字地址寻址,只能通过包含寄存器编号的指令操作码(在源代码中被命名为 ax, bx, ...).

这意味着你的问题中没有寄存器,在其中谈论寄存器是没有意义的。

在普通汇编器中 [B+2] 将是 BYTE 40,(B 处的字节是:30、0、40、0、70、0、11、0)。在 MASM 中,它可能有所不同,因为它试图与 "variables" 一起工作,同时考虑它们的大小,因此 [B+2] 可能被视为 WORD 70。我不确定,我不想要知道,MASM 有太多的怪癖,无法按逻辑使用,你必须学习它们。 (只需使用 B WORD 0, 1, 2, 3, 4 MOV ax,[B+2] 创建短代码并检查调试器中的反汇编)。

[A+2] 是 10。您忽略了 [A] 是 [A+0] 的要点。就像在 C/C++ 数组中一样,索引从 0 开始,而不是从 1 开始。

如果您在纸上绘制字节(例如 DWORD 0x310 编译为 10 03 00 00 六字节),则可以轻松找出其余答案。

我想知道你在第一个可能的答案中得到 0x15 的位置,因为我在 A 中没有看到任何值 21。


根据新评论进行编辑...我会 "compile" 为您完成,确保您理解每个字节,或者在回答下询问哪个字节不清楚。

; A BYTE 0xB, 0d20, 0d10, 0d13, 0x0C
A:
    0B 14 0A 0D 0C
; B WORD 0d30, 0d40, 0d70, 0hB 
B: ;▼     ▼     ▼     ▼
    1E 00 28 00 46 00 0B 00
; D DWORD 0xB0, 0x200, 0x310, 0x400, 0x500, 0x600 
D: ;▼           ▼           ▼           ▼           ▼           ▼
    B0 00 00 00 00 02 00 00 10 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00

请注意 ABD 只是标记内存中某个地址的标签,这就是大多数汇编程序使用符号的方式。在 MASM 中它更棘手,因为它试图成为 "clever" 并且不仅保留地址,而且它知道 D 被定义为 DWORD 而不是 BYTE。不同的汇编程序不是这种情况。

现在 MASM 中的 [D+4] 是棘手的,它可能会使用大小知识来默认该表达式的 DWORD 大小(在其他汇编器中你应该指定,比如 "DWORD PTR [D+4]",或者它被推导如果可能,自动从目标寄存器大小)。所以 [D+4] 将获取字节 00 02 00 00 = DWORD 00000200。 (我只希望 MASM 也不要将 +4 偏移量重新计算为 +4 个双字,即以字节为单位的 +16)。

现在针对您的评论,我会将它们撕成小块并带有错误,因为虽然通常很容易理解您的意思,但在 Assembly 中,一旦您开始编写代码,仅仅有良好的意图是不够的,您一定要准确无误,CPU不会填空,照你写的做。

Can you explain how did you get 0d13 of A and through to 0d30 of B @Jester?

转到我的 "compiled" 字节,D-1(当偏移量以字节为单位时)表示从 D: 地址返回一个字节,即。 B 行末尾的 00。现在 D-10D: 算回 10 个字节...这将转到 A 行中的 0D,因为 B 数组中有 8 个字节,并且剩下的两个在 A 数组的末尾。

现在,如果您从该地址读取 4 个字节:0D 0C 1E 00 = DWORD 001E0C0D。 (Jester 在他的最终 "dword" 值中不小心将小数 13 混成了 13h

each value in B will occupy two "slots" as you count back? And each value in A will occupy four "slots"?

反过来,B 中的两个值将构成 1 个 DWORD 槽,A 中的四个值将构成 1 个 DWORD。正如 "D" 6 个 DWORD 的数据也可以被视为 12 个 WORD 值,或 24 个 BYTE 值。例如 DWORD PTR [A+2]1E0C0D0A.

first value of A,B, and D are offsets x86 is little endian

"value of A" 实际上是一些内存地址,我想在这种情况下我自动不提及 "value",但是 "address"、"pointer" 或 "label"(虽然"value of symbol A"是有效的英文句子,符号分配地址后可以解析)。

OFFSET A 在 MASM 中具有特殊的特殊含义,从它的段开始获取地址 A 的字节偏移量(在 32b 模式下,这通常是人类的 "address",因为段从 0 开始,内存是平面映射的。在实模式下,地址的段部分很重要,因为偏移量只有 16 位(只能通过偏移量寻址 64k 内存)。

在你的情况下,我会说 "value at A",如 "content of memory at address A"。这很微妙,我知道,但是当每个人都这样说话时,就很清楚了。

B is 0d40

[B+2]40B+2 是某个地址+2。 B 是一些地址。这是标记 "value from memory at x".

[x] 括号

虽然在 MASM 中有点不同,它会将 mov eax,D 编译为 mov eax,DWORD PTR [D] 以模仿 "variable" 用法,但这是 MASM 的特定怪癖。避免使用该语法,它隐藏了未聚焦 reader 源的内存使用情况,即使在 MASM 中也使用 mov eax,[D](或者理想地摆脱 MASM)。

D...bytes (in hex) = 0x200, 0,0,0,...

0x200 不是字节,十六进制格式具有整洁的特征,即两个数字对形成单个字节。所以 hexa 200 是 3 位数字 => 一个半字节。

考虑这些 DWORD 值是如何从字节创建的。在十进制格式中,您将不得不重新计算整个值,因此字节 40、30、20、10 是 40 + 30*256 + 20*65536 + 10* 16777216 = 169090600 -> 原始值在那里不可见。使用 hexa 28 1E 14 0A,您只需按正确的顺序重新组装它们 0A141E28.

D is 0x200.

不是,D是地址。甚至 [D] 也是 0xB0.

Count 10 bytes backwards from 0xb0. So wouldn't [D-10] be equal to 0x0C?

B0 位于 D+0 地址。您不将其计入 [D-10] 中的那 10 个字节,即 B0 是超出 D (D+0) 的零字节。查看我的 "compiled" 内存并计算那里的字节数以熟悉偏移量。