【问题标题】:Array in Hexadecimal in Assembly x86 MASM汇编 x86 MASM 中的十六进制数组
【发布时间】:2016-10-16 00:59:02
【问题描述】:

如果: (我相信寄存器是相邻的......)

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

然后:

  • 什么是[A+2]?答案是 0d20 或 0x15
  • 什么是 [B+2]?答案是 40 或 0x28
  • 什么是 [D+4]?不确定
  • 什么是[D-10]?不确定

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

编辑

这是因为:考虑到 A、B 和 D 的第一个值是偏移量 x86 是小端序... A = 0d10,从那里再数 2 B...字节(十进制)= 30,0,40,0,70,0,11,0 B 是 0d40,从那个 D...bytes (in hex) = 0x200, 0,0,0,...0,2 再计算 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。那是对的吗?谢谢!! 编辑

【问题讨论】:

  • 答案取决于操作数的大小以及您的汇编程序是使用字节偏移还是类型化索引。
  • 不知道MASM用什么,但第一个答案肯定是错的。记住偏移量从零开始。这就是0d10[B+2] 对字节偏移是正确的。 [D+4] 只是 0x200 因为 4 个字节只是第二个 dword。 [D-10] 很棘手,它将从A0d13 开始,一直到B0d30,给你0x001E0C13(由于小端序)。
  • 哦,现在我明白了,那些“20 或 0x15”和“40 或 0x28”表示相同的数字,对吧?然后你转换了 20 个错误,它是 0x14 (1*16 + 4 = 20)。无论如何,尽快学会编译一些东西+在调试器中启动它,在那里你可以使用内存窗口来验证产生了哪些字节,并在指令视图中查看如何将哪些地址编译成那些 +2 的指令。
  • 你能解释一下你是如何得到 A 的 0d13 和 B @Jester 的 0d30 的吗?谢谢你。是不是因为两个 WORD 等于一个 DWORD,那么当你倒数时,B 中的每个值都会占用两个“槽”? A 中的每个值都会占用四个“槽”?谢谢。
  • 所以是因为:考虑到 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 吗?谢谢

标签: arrays memory assembly x86 masm


【解决方案1】:

WORD 是 2 个字节。 DWORD 是两个 WORD(“D”代表“双”)。 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 本身上的特殊微小内存位,不能像上面那样通过数字地址来寻址,而只能通过包含寄存器数量的指令操作码来寻址(在源代码中它们被命名为 axbx, ...)。

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

在普通汇编程序中,[B+2] 为 BYTE 40,(B 处的字节为:30、0、40、0、70、0、11、0)。在 MASM 中可能会有所不同,因为它正在尝试使用“变量”同时考虑它们的大小,因此 [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。


编辑由于新的 cmets ... 我会为你“编译”它,确保你理解每个字节,或者在答案下询问哪个不清楚。

; 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 中它更加棘手,因为它试图变得“聪明”并且不仅保留地址,而且它知道 D 被定义为 DWORD 而不是 BYTE。不同的汇编器并非如此。

现在 MASM 中的 [D+4] 很棘手,它可能会使用大小知识默认为该表达式的 DWORD 大小(在其他汇编程序中,您应该指定,例如“DWORD PTR [D+4]”,或者它是推导出来的如果可能,自动从目标寄存器大小中提取)。所以 [D+4] 将获取字节 00 02 00 00 = DWORD 00000200。 (我只是希望 MASM 不会将 +4 偏移量重新计算为 +4th dword,即 +16 字节)。

现在对于您的 cmets,我会将它们撕成碎片,有错误,因为虽然通常很容易理解您的意思,但在汇编中,一旦您开始编写代码,仅仅有良好的意图是不够的,您必须准确和准确,CPU不会填补任何空白,并完全按照您写的内容。

你能解释一下你是如何得到 A 的 0d13 和 B @Jester 的 0d30 的吗?

转到我的“编译”字节,D-1(当偏移量以字节为单位时)表示从D: 地址返回一个字节,即。 00 在 B 行的末尾。现在对于D-10 count 10 bytes back from D: ...这将转到A行中的0D,因为8个字节在B数组中,其余两个在A数组的末尾.

现在,如果您从该地址读取 4 个字节:0D 0C 1E 00 = DWORD 001E0C0D。 (Jester 在他的最终“dword”值中意外地将十进制 13 混入了 13h

当您倒数时,B 中的每个值将占用两个“槽”?而A中的每个值都会占用四个“槽”?

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

A、B 和 D 的第一个值是偏移量 x86 是小端序

“A的值”实际上是一些内存地址,我想我在这种情况下自动不提到“值”,而是“地址”,“指针”或“标签”(虽然“符号A的值”是有效的英文句子,可以在符号分配地址后解析)。

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

在您的情况下,我会说“值 at A”,即“地址 A 处的内存内容”。我知道这很微妙,但是当每个人都这样说话时,它就很清楚了。

B 是 0d40

[B+2]40B+2 是某个地址+2。 B 是某个地址。这是 [x] 括号标记“内存中的值 x”。

虽然在 MASM 中它有点不同,但它会将 mov eax,D 编译为 mov eax,DWORD PTR [D] 以模仿“变量”用法,但这是 MASM 的特定怪癖。避免使用该语法,它会向不专心的源代码读者隐藏内存使用情况,即使在 MASM 中也使用mov eax,[D](或理想情况下摆脱 M​​ASM)。

D...字节(十六进制)= 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 是 0x200。

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

从 0xb0 倒数 10 个字节。那么 [D-10] 不等于 0x0C 吗?

B0 位于 D+0 地址。你不计入 [D-10] 中的这 10 个字节,B0 是在D (D+0) 之外的零字节。查看我的“编译”内存并计算那里的字节数以适应偏移量。

【讨论】:

    猜你喜欢
    • 2022-11-14
    • 1970-01-01
    • 2012-07-28
    • 2012-03-10
    • 2014-04-08
    相关资源
    最近更新 更多