在x86中将字符串定义为字节(db)和将字符串定义为单词/双字(dw / dd)有什么区别

Wil*_*iam 4 linux x86 assembly nasm

我正在尝试研究在汇编中定义标签之间的区别,这是一个示例

ALabel: db 'Testing'
AAnotherLabel: dw 'Testing'
Run Code Online (Sandbox Code Playgroud)

现在,让我将它们加载到32位寄存器中:

mov eax, [ALabel]
mov ebx, [AAnotherLabel]
Run Code Online (Sandbox Code Playgroud)

在对gdb进行调查后,我发现eax和ebx的所有子寄存器都包含相同的值,请看这里:

info register eax
0x64636261 //dcba

info register ebx
0x64636261 //dcba
Run Code Online (Sandbox Code Playgroud)

他们是一样的!

在杰夫·邓特曼(Jeff Duntemann)的书(使用Linux进行汇编语言逐步编程)中,他展示了单词和双字进入寄存器的示例,但由于某种原因加载了偏移量(即,值的地址类似)

DoubleString: dd 'Stop'
mov edx, DoubleString
Run Code Online (Sandbox Code Playgroud)

对edx内容的调查表明,它包含一个地址,大概是字符串中前四个字母的地址,与仅第一个字母的地址相对应,尽管我在这里进行了推测。

我想弄清楚这里实际发生的情况,实际上是该语句是否将字符串中第一个字母的地址加载到寄存器中:

Fin: db 'Final'
mov ecx, Fin
Run Code Online (Sandbox Code Playgroud)

Ble*_*ose 5

您在这里谈论2种不同的事情。

db,dw,dd
Jester 之间的区别已经为您提供了正确的答案。这是NASM手册中的两个示例,应该可以帮助您理解它。

使用dw时,以1字(2字节)的步长创建存储。因此,它只能具有2、4、6、8 ...个字节的大小。在此示例中,您有一个3字节的字符串'abc'。它只需要3个字节,但是因为您使用了'dw',所以它将是4个字节长。4.字节用0填充。

fin: dw 'abc'               ; 0x61 0x62 0x63 0x00 (string)
Run Code Online (Sandbox Code Playgroud)

通过使用db而不是dw,您可以1字节的步长创建存储。这将是3个字节长:

fin: db 'abc'               ; 0x61 0x62 0x63 (string)
Run Code Online (Sandbox Code Playgroud)

它们之所以称为伪指令,是因为实际上它们是您的汇编器(在本例中为NASM)中的命令,它告诉他如何分配您的存储。它不是您的处理器必须读取的代码。来源:
3.2.1:http : //www.nasm.us/doc/nasmdoc3.html

括号和无括号
您所谈到的另一件事是是否使用括号[]。这再次涉及到NASM的语法。如果不使用方括号,则告诉NASM使用该地址。这会将内存地址保存在eax中:

mov eax, fin
Run Code Online (Sandbox Code Playgroud)

这将从eax的内存地址中保存前4个字节:

mov eax, [fin]
Run Code Online (Sandbox Code Playgroud)

关于最后一个问题:

DoubleString: dd 'Stop'
mov edx, DoubleString
Run Code Online (Sandbox Code Playgroud)

DoubleString,存储地址,'Stop'保存在edx中。每个地址对应一个字节。因此,地址DoubleString直接指向字母'S'。地址Doublestring+1指向't'存储字母的下一个字节,依此类推。

来源:
2.2.2:http : //www.nasm.us/doc/nasmdoc2.html#section-2.2.2