汇编 x86 Irvine WriteString Byte 与 Dword

Assembly x86 Irvine WriteString Byte vs Dword

我刚刚注意到一些有趣的事情,我正在努力加深了解。 我尝试使用 Irvine WriteString 调用。

写入字符串

Write a null-terminated string.
Input: DX points to the strings offset

INCLUDE Irvine32.inc

.data
    fizz        BYTE    "Fizz",  0

...

MOV EDX, OFFSET fizz
CALL WriteString
CALL CrLf

并且工作完美 我可以在我的 window 中看到“Fizz”,就像在 documentation.

中一样

但是,如果我尝试使用 DWORD 而不是 BYTE

fizz        DWORD   "Fizz",  0

我要在提示 window 中看到“zziF”。 据我所知,唯一的区别是 BYTE 和 DWORD,以位为单位的大小(8 位与 32 位)。 我真的不明白相反的顺序。发生什么事了?

感谢每一个回答!

您的问题与"Irvine"或"WriteString"完全无关。

简短的回答是,您所看到的是您在 Intel x86 架构上编程的直接结果,即 little endian ,而你使用的是某个老黑客编写的汇编程序。

长答案如下。

如果你正在处理汇编语言,那么你应该通过在维基百科或其他地方查找它来学习关于 endianness 的所有知识,但简而言之,它定义了字节如何存储在连续的内存位置以形成大于字节的数量。有两种类型的字节顺序:

  • 大端,以及
  • 小端

Little endian 意味着在大于字节的数量上,首先存储最不重要的 ("low") 字节,然后依次存储重要的字节。因此,在 DWORD 中,首先存储最不重要的 ("low") 词,然后是最重要的 ("high") 词。这与big endian相反,高字节先存。您可能认为大端更直观,因为它更符合我们人类表示数字的方式,最重要的数字是最左边的数字,次要数字紧随其后,但这只是我们人类,完全是任意的;数字的性质并没有规定数字的重要性应该从左到右或从右到左排序。相反,little endian有一定的硬件优势,这也是英特尔选择x86架构的原因。

不过我跑题了

所以,这是正在发生的事情:

您正在使用的汇编器很聪明,允许您使用字符串文字指定 DWORD 的值。这是荒谬的,因为 DWORD 应该包含 32 位 数字 ,而不是字符串,但他们正试图适应肮脏的黑客攻击。这也完全是任意的,因为有很多方法可以想象可以实现这样的怪癖,而他们只是选择了一种方法,我想是他们最喜欢的一种。

因此,很明显,他们所做的是获取您的字符串文字,并将其视为构成 DWORD 的一组四个字符。当然,当他们将 DWORD 存储在内存中时,他们将其存储在小端,这适用于英特尔架构,这意味着您得到 "zziF" 而不是 "Fizz"。重要的是要了解此 "zziF" 由汇编程序嵌入到您的程序中,并且 "WriteString" 函数按它看到的那样打印它。如果您使用任何其他打印字符串的函数,也会打印相同的内容。这不是函数的错。