0

我无法理解处理器到底在做什么以及为什么在我的 asm32 作业中

MOV DX,07c8
XCHG DL,DH
MOV WORD PTR Vet[93],DX
ROR BYTE PTR Vet[94],5
PUSH WORD PTR Vet[93]
POP Ris1 

据我了解,它应该是这样的:

1.DX注册表=07C8

2.DX=C807

3.兽医[93]=07,兽医[94]=C8

4.C8 变为 46 所以 Vet[93]=07,vet[94]46

5.我推07然后我推46

6.我弹出两次(因为 Ris1 的大小是 32 位)并且因为我必须首先弹出最后一个推送的值,所以我得到 46 07(十六进制)作为 Ris1 的结果。

编译器本身显示结果确实是 46 07 h,我很难理解的是为什么它是 46 07h 而不是 07 46h ......我猜它与 push and pop 命令有关,但我不确定......

它与小端/大端有关还是我猜对了?

谢谢你的时间^^。

4

2 回答 2

1

事实上,它与ednianness有关。在您的情况下,代码似乎是在 little-endian CPU(例如 x86 架构)上执行的。这意味着存储在内存中的数据的字节顺序与存储在寄存器中的数据的字节顺序相反。它对 8 位值没有影响,但包含 16 位或 32 位变量的字节在存储到 RAM 时会反转,在加载到 CPU 时会反转回来。

通常是一个透明的过程,不会破坏程序员的意图。但是您的示例很棘手,因为数据的解释在执行过程中会发生变化:

  1. MOV WORD PTR Vet[93], DX存储低字节Vet[93]和高字节Vet[94]——C807被存储为寄存器⇄内存07C8操作——此时您的解释是正确的;

  2. 然后将高字节更改ROR字节值-我们得到0746-您仍然是正确的;

  3. 然后将整个 16 位值4607从内存中压入堆栈,这是一个不改变字节顺序的内存⇄内存操作,所以我们还有0746;

  4. 最后,您弹出该值并将其存储在一个 16 位变量中,这又是一个不涉及任何字节顺序更改的 memory⇄memory 操作,因此您最终会0746在内存中获得字节。但是这些字节表示4607的 16 位值,因为我们总是以寄存器字节顺序解释内存中的数据,而这又取决于该值的假定字节宽度。

所以确实,你有0746字节Ris1,但这编码了4607值。您可以稍后将其存储Ris1在一个寄存器中,该寄存器会将字节反转为4607,但值仍为4607

值字节顺序 = 寄存器字节顺序≠内存字节顺序。


PUSH/POP操作在这里没有影响。这些是原子操作(您推送一次并弹出一次),在您的情况下,它只是在内存位置(堆栈内存)之间移动 16 位数据。

Ris1必须是 16 位值,否则在进入代码块之前必须保证堆栈顶部包含两个零字节。否则 32 位的两个高字节Ris1将是未定义的。

于 2013-08-30T23:35:34.517 回答
1

查看您的原始代码和最初的评论:

    MOV DX,07c8
  1. DX 注册表 = 07C8h []

    XCHG DL,DH

  2. DX = C807 []

    MOV WORD PTR Vet[93],DX

  3. Vet[93] = 07, Vet[94] = C8 [是的,因为 x86 是小端:低字节到低地址]

    ROR BYTE PTR Vet[94],5

  4. C8变成46这样Vet[93]= 07, vet[94]= 46[]

    PUSH WORD PTR Vet[93]

  5. 我 push07然后我 push 46[ NO... stack go high memory to low memory,所以如果你一次看一个字节的堆栈,那么46首先会紧随其后07;但是... x86 将一个字推入内存,它并没有真正一次推入一个字节;内存顺序是由于 x86 字节序]

    POP Ris1

  6. 我弹出两次(因为 Ris1 的大小是 32 位)并且因为我必须首先弹出最后一个推送的值,所以我在 Ris1 中得到 46 07(十六进制)。[不...pop Ris1从堆栈中弹出一个单词。它不会“弹出两次”。由于 x86 字节序,它将保持正确的字节顺序。]

于 2013-08-31T14:31:59.320 回答