【问题标题】:NASM modifying a stringNASM 修改字符串
【发布时间】:2017-09-26 12:41:50
【问题描述】:

我是使用 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

此时,我被难住了。 谁能提供任何关于为什么会发生这种情况以及我应该如何解决它的见解?我的基础错了吗?在此先感谢您的帮助

【问题讨论】:

    标签: assembly x86 nasm


    【解决方案1】:

    mov [name], dword 'Nuhas' 失败,因为 DWORD 有四个字节长,但 Nuhas 有五个字节长。这并不奇怪,汇编程序准确地告诉你哪里出了问题,它甚至以两种不同的方式说出来:“字符常量太长”和“dword 数据超出范围”。您只是无法将 5 个字节放入只能容纳 4 个字节的地方。

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

    编辑

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

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

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

    【讨论】:

    • 您可能会提到解决方案,即将对内存的写入拆分为多个位,每个位的长度最多为 4 个字节。 name 变量长 9 个字节;它有足够的空间。
    • 第一部分对我来说很有意义,但是至于第二部分,为什么名称只有 4 个字节长,因为我设法将 Zara Ali 放入其中,这应该意味着它是 8 个字节(或 9正如@CodyGray 刚才所说)并且应该有足够的空间来容纳一个 8 字节的 qword
    • 是9个字节,最后一个字节是0xa。在 32 位系统上,您不能一次移动一个 QWORD。您必须移动 2 个 DWORD。当然是小端。 @eames
    • 啊,这就是我要找的东西,但是我如何分割内存呢?有这个命令吗?
    • 你不需要“分割内存”。我什至不知道那是什么意思。您只需写 2 个 DWORD:mov DWORD [name], lowDword 后跟 mov DWORD [name+4], highDword
    猜你喜欢
    • 2016-08-11
    • 1970-01-01
    • 2014-05-30
    • 2018-04-10
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多