NASM 修改字符串

NASM modifying a string

我刚开始使用 Assembly(所有类型),所以我一直在学习 tutorialspoint.com 中的教程 特别是,我在有关程序集寻址的页面 https://www.tutorialspoint.com/assembly_programming/assembly_addressing_modes.htm 上。一切正常,直到给出代码的最后一个示例(取名 Zara Ali 并将其更改为 Nuha Ali):

section .text
   global _start     ;must be declared for linker (ld)
_start:             ;tell linker entry point

   ;writing the name 'Zara Ali'
   mov  edx,9       ;message length
   mov  ecx, name   ;message to write
   mov  ebx,1       ;file descriptor (stdout)
   mov  eax,4       ;system call number (sys_write)
   int  0x80        ;call kernel

   mov  [name],  dword 'Nuha'    ; Changed the name to Nuha Ali

   ;writing the name 'Nuha Ali'
   mov  edx,8       ;message length
   mov  ecx,name    ;message to write
   mov  ebx,1       ;file descriptor (stdout)
   mov  eax,4       ;system call number (sys_write)
   int  0x80        ;call kernel

   mov  eax,1       ;system call number (sys_exit)
   int  0x80        ;call kernel

section .data
name db 'Zara Ali', 0xa

这段代码当然有效,但是,当稍微修改它时,我 运行 遇到了问题。在第 13 行,我将 'Nuha' 更改为 'Nuhas' 只是为了看看它是否会出现 'NuhasAli' (因为我假设该行只是用 Nuhas 和保留其余部分(Ali))。

当我尝试这个和 运行 命令 'nasm -f elf helloasm.asm'(helloasm.asm 是文件的名称)时,它给了我这两条消息:

helloasm.asm:13: warning: character constant too long
helloasm.asm:13: warning: dword data exceeds bounds

我找不到对第一个问题的任何见解,因为当我查找它时,它给我的只是关于 C 和 C++ 的结果。但是,对于第二个警告,我试图通过简单地将其设为 qword 而不是 dword

来使 dword 数据停止超出范围
section .text
   global _start     ;must be declared for linker (ld)

_start:             ;tell linker entry point

   ;writing the name 'Zara Ali'
   mov  edx,9       ;message length
   mov  ecx, name   ;message to write
   mov  ebx,1       ;file descriptor (stdout)
   mov  eax,4       ;system call number (sys_write)
   int  0x80        ;call kernel

   mov [name], qword 'Nuhas'    ; Changed the name to Nuha Ali

   ;writing the name 'Nuha Ali'
   mov  edx,10      ;message length
   mov  ecx,name    ;message to write
   mov  ebx,1       ;file descriptor (stdout)
   mov  eax,4       ;system call number (sys_write)
   int  0x80        ;call kernel

   mov  eax,1       ;system call number (sys_exit)
   int  0x80        ;call kernel

section .data
    name dw 'Zara Ali', 0xa
helloasm.asm:13: warning: character constant too long
helloasm.asm:13: error: operation size not specified

在这一点上,我被难住了。 任何人都可以深入了解为什么会发生这种情况以及我应该如何解决它吗?我的基本原理错了吗?在此先感谢您的帮助

mov [name], dword 'Nuhas' 失败,因为 DWORD 是四个字节长,但 Nuhas 是五个字节长。这没什么奇怪的,汇编器会准确地告诉你哪里出了问题,它甚至用两种不同的方式来表达:"character constant too long" 和 "dword data exceeds bounds"。你不能将 5 个字节放入一个只能容纳 4 个字节的地方。

mov [name], qword 'Nuhas' 显然失败了,因为 nameDWORD,而不是 QWORD,如果您设法将 8 个字节塞入其中,您可能会损坏紧随其后的记忆。

编辑

我想造成混淆的原因是您找到的示例代码有 name dw 'Zara Ali', 0xa,这可能让您相信您可以将整个文本放入 DWORD。我不知道他们为什么用dw,我觉得他们应该用db。他们能够做到这一点的唯一原因是因为汇编器允许这种黑客攻击,但为了让他们的示例代码易于理解和直观,他们应该使用 db,因为这就是你在那里声明的: 一个字节序列。

无论如何,dw指令与mov [name], dword 'wxyz'指令无关。 dw 指令声明了一个任意长度的 DWORD 序列。 mov 指令可以复制固定数量的字节:单个字节,或两个字节 (a WORD) 或四个字节 (a DWORD)。 (或者甚至八个字节,一个 QWORD,如果有任何指令可以以某种方式指定一个四字操作数,尽管我现在想不出任何指令。)汇编器可能会执行一些基本的类型检查,确保目标数量是适合接收源数量的类型,并且检查通过,因为 name 已用 dw 定义,并且存储的数量作为 DWORD 给出.

因此,mov [name], dword 'wxyz' 指令实际上是一个 hack:它将您提供的四个字符打包成一个 DWORD,并将其存储在 [name] 中。 name 已经用 dw 定义,所以它是正确的类型,所以 hack 有效。但是,一个 DWORD 中只能包含四个字符,这就是 'Nuhas' 不起作用的原因。此外,您不能执行 name dq 'bla bla bla' 并期望 mov [name], qword 'wxyzwxyz' 工作,因为没有指令会移动立即 qword,因为您正在使用的指令集是 32 位的。 (您可以使用 64 位指令集来做到这一点。)