由于某些原因[msgLen]和msgLen产生相同的结果。我知道我应该使用equ或其他什么,但我想知道为什么这不起作用。NASM是否忽略了取消引用?它打印了我的绳子和一堆垃圾,因为它认为绳子比它大,对吧?谢谢
请参阅下面的组件:
_start:
mov edx,[msgLen]
mov ecx,msg
mov ebx,1
mov eax,4
int 0x80
mov eax,1
int 0x80
section .data
msg db 'Zoom',0xA
msgLen db $-msg
使用调试器在加载后查看EDX,或者使用strace ./a.out
查看实际传递给系统调用的长度它会有所不同(地址与加载的值(。这两种方法都有不同的缺陷,恰好会产生大的值,所以效果只是碰巧相同。调试/跟踪工具会清楚地向你表明,NASM不是";忽略解引用";,虽然
mov edx, msgLen
是地址,就在消息旁边。如果您使用ld -melf_i386 -o foo foo.o
链接到一个标准的Linux非PIE静态可执行文件,它将类似于0x804a005
。
mov edx, [msgLen]
从该地址(EDX的宽度(加载4个字节,在数据段中,您只将大小组装为1个字节。3个高字节来自映射到该内存页的文件部分的下一个字节。
当我只使用nasm -felf32 foo.asm
组装并使用ld -melf_i386
链接时,恰好是3个字节的零,所以我不会从dword加载版本中得到任何垃圾打印。(x86是little-endian(。
但你的非零字节似乎是调试信息。我发现NASM的调试信息与有用信息相反,有时会使GDB的反汇编变得混乱(layout reg
/layout asm
有时无法反汇编标签后的整个块(,所以我不使用它。
但如果我使用nasm -felf32 -Fdwarf
,那么我确实会从经过.data
部分末尾的dword加载中获得7173
。这是一个不同的大数字,所以这在不同的方面是错误的,而不是同一个问题。7173
是0x1c05
,因此它对应于db 5, 0x1c, 0, 0
。也就是说,你计算的长度5是低字节,但后面有一个0x1c
。yasm -gdwarf2
给了我469762053
=0x1c000005
。
如果使用db $-msg, 0,0,0
或dd $-msg
,则可以加载整个dword。(要将字节加载到双字寄存器并进行零扩展,请使用movzx edx, byte [mem]
(
write()
大长度行为
如果给它一个非常大的长度,write
将一直到它到达一个不可读的页面,然后返回它实际写入的长度。(在开始copy_from_user
之前,它不会检查整个缓冲区的可读性。如果在遇到不可读的页面之前写入的字节数为非零,它会返回。只有在立即遇到不可读页面时,才能获得-EFAULT
,而不是在稍后传递包含一些未映射页面的巨大长度时。(
例如使用mov edx, msgLen
(标签地址(
$ nasm -felf32 -Fdwarf foo.asm
$ ld -melf_i386 -o foo foo.o
$ strace -o foo.tr ./foo # write trace to a file so it doesn't mix with terminal output
Zoom
foo.asmmsgmsgLen__bss_start_edata_end.symtab.strtab.shstrtab.text.data.debug_aranges.debug_info.debug_abbrev.debug_lin! ' 6& 9B_
$ cat foo.tr
execve("./foo", ["./foo"], 0x7fffdf062e20 /* 53 vars */) = 0
write(1, "Zoomn534 2 4 22041035 "..., 134520837) = 4096
exit(1) = ?
+++ exited with 1 +++
134520837
是您传递的长度,0x804a005(msgLen
的地址(。系统调用在到达未映射的页面并提前停止之前写入4096个字节,即1整页。**您传递的数字高于这个数字并不重要,因为在映射结束之前只有1页。(msg:
显然就在那一页的开头。(
在终端上(