我是使用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
此时,我很难过。 任何人都可以提供任何有关为什么会发生这种情况以及如何解决这个问题的见解?我的基本原理是错的吗?在此先感谢您的任何帮助
答案 0 :(得分:2)
DWORD
失败,因为Nuhas
长度为四个字节,但mov [name], qword 'Nuhas'
长度为五个字节。这没有什么奇怪的,汇编器正在告诉你究竟出了什么问题,甚至用两种不同的方式说:“字符常量太长”和“双字数据超出界限”。你只能将5个字节放入一个只能容纳4个字节的地方。
name
显然失败是因为DWORD
是QWORD
,而不是name dw 'Zara Ali', 0xa
,如果你以某种方式设法将8个字节塞入其中,你可能会破坏内存紧随其后。
修改强>
我想混淆源于你找到的示例代码DWORD
这一事实,这可能会让你相信你可以将整个文本放在dw
中。我不知道为什么他们使用db
,在我看来他们应该使用db
。他们能够做到这一点的唯一原因是因为汇编程序允许这种黑客,但为了使他们的示例代码易于理解和直观,他们应该使用dw
,因为那就是你在那里声明的:一个字节序列。
在任何情况下,mov [name], dword 'wxyz'
指令都与dw
指令无关。 DWORD
指令声明mov
s的任意长度序列。 WORD
指令可以复制固定数量的字节:单个字节,或两个字节(一个DWORD
)或四个字节(一个QWORD
)。 (或者甚至可能是8个字节,一个name
,如果有任何指令可以某种方式指定一个四字操作数,虽然我现在也想不到。)汇编程序可能执行一些基本的类型检查,确保目标数量属于适合接收源数量的类型,并且检查通过,因为dw
已定义为DWORD
,并且存储的数量为mov [name], dword 'wxyz'
所以,[name]
指令实际上是一个hack:它将你给它的四个字符打包成一个DWORD,然后将它存储在name
中。已使用dw
定义name dq 'bla bla bla'
,因此它的类型正确,因此黑客可以正常工作。但是,DWORD中只能包含四个字符,这就是“Nuhas”无效的原因。此外,您无法执行mov [name], qword 'wxyzwxyz'
并期望{{1}}起作用,因为没有指令可以移动立即qword,因为您使用的指令集是32位。 (您可以使用64位指令集执行此操作。)