ASM 32分配怀疑

时间:2013-08-30 18:19:19

标签: assembly x86 stack endianness

我在解决处理器究竟在做什么以及为什么在我的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.Vet [93] = 07,Vet [94] = C8

4.C8变为46,因此Vet [93] = 07,兽医[94] 46

5.我推07然后我推46

6.I弹出两次(因为Ris1的大小是32位)并且由于我必须首先弹出最后一个推送值,因此在Ris1中得到46 07(十六进制)。

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

它与小Endian / big Endian有关还是我猜对了?

谢谢你的时间^^。

2 个答案:

答案 0 :(得分:1)

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

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

  1. MOV WORD PTR Vet[93], DXVet[93]中存储低字节,在Vet[94]中存储高字节 - C807 存储为 07 < kbd> C8 因为它是寄存器记忆操作 - 此时你的解释是正确的;

  2. 然后用ROR作为字节值更改高字节 - 我们得到 07 46 - 你& #39;仍然正确;

  3. 然后从堆栈的内存中推出整个16位值 4607 ,这是一个不改变字节顺序的内存存储器操作,所以我们仍然有 07 46

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

  5. 确实,Ris1中有 07 46 个字节,但这会编码 4607 值。您可以稍后将Ris1存储在一个寄存器中,该寄存器将字节反转为 46 07 ,但该值仍为 4607

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


    PUSH / POP操作对此没有影响。这些是原子操作(你按一次并弹出一次)在你的情况下只是在内存位置之间移动16位数据(stack 内存)。

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

答案 1 :(得分: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] = 07vet[94] = 46 [ ]

    PUSH WORD PTR Vet[93]

  5. 我按07然后我按46 [ NO ...堆栈将高内存转到内存不足,所以如果你一次查看堆栈一个字节,然后46将首先跟随07;但是...... x86将一个单词推入内存,它一次不会真正推送一个字节;内存顺序是由于x86字节顺序]

    POP Ris1

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