Assembly Linux 64位Windows子系统上的32位系统调用或可执行文件?还是一个工作的64位Hello World?
我试图学习NASM,从helloworld项目开始。它本身就是Linux上的32位NASM 我复制并粘贴创建的Assembly Linux 64位Windows子系统上的32位系统调用或可执行文件?还是一个工作的64位Hello World?,assembly,x86-64,nasm,system-calls,windows-subsystem-for-linux,Assembly,X86 64,Nasm,System Calls,Windows Subsystem For Linux,我试图学习NASM,从helloworld项目开始。它本身就是Linux上的32位NASM 我复制并粘贴创建的helloworld.asm(使用int 0x8032位系统调用)并输入命令 nasm -f elf helloworld.asm ld -m elf_i386 helloworld.o -o helloworld 这两个看起来不错,但运行/helloworld会产生 -bash:./helloworld:无法执行二进制文件:Exec格式错误 然后我搜索了这个错误,喜欢上了这个。我输入
helloworld.asm
(使用int 0x80
32位系统调用)并输入命令
nasm -f elf helloworld.asm
ld -m elf_i386 helloworld.o -o helloworld
这两个看起来不错,但运行/helloworld
会产生
-bash:./helloworld:无法执行二进制文件:Exec格式错误
然后我搜索了这个错误,喜欢上了这个。我输入了该答案的命令:
sudo apt-get install gcc-multilib g++-multilib
之后,我安装了这个:
nasm -f elf64 helloworld.asm -o helloworld.o
ld -o helloworld helloworld.o -m elf_x86_64
两者都来自该答案,没有出现错误。然后我执行了
/helloworld
,得到了以下错误:
分段故障(堆芯转储)
好的,然后我也搜索了这个新错误。(编者按:解释确切原因:WSL 1不支持64位代码中的32位int0x80
系统调用,这通常不是一个好主意)
大多数答案并没有给出确切的答案。我唯一得到的。“看起来我需要修改NASM代码,”他说
64bit sys_exit = 60 32bit sys_exit = 1
64bit sys_write = 1 32bit sys_write = 4
及
所以我修改了原始代码,它变成了:原代码:
; Hello World Program - asmtutor.com
; Compile with: nasm -f elf helloworld.asm
; Link with (64 bit systems require elf_i386 option): ld -m elf_i386 helloworld.o -o helloworld
; Run with: ./helloworld
SECTION .data
msg db 'Hello World!', 0Ah
SECTION .text
global _start
_start:
mov edx, 13
mov ecx, msg
mov ebx, 1
mov eax, 4
int 80h
mov ebx, 0 ; return 0 status on exit - 'No Errors'
mov eax, 1 ; invoke SYS_EXIT (kernel opcode 1)
int 80h
修改后的代码:
; Hello World Program - asmtutor.com
; Compile with: nasm -f elf helloworld.asm
; Link with (64 bit systems require elf_i386 option): ld -m elf_i386 helloworld.o -o helloworld
; Run with: ./helloworld
SECTION .data
msg db 'Hello World!', 0Ah
SECTION .text
global _start
_start:
mov edx, 13
mov ecx, msg
mov rdi, 1
mov rax, 1 ; SYS_write 64-bit ABI
syscall
mov rdi, 0 ; return 0 status on exit - 'No Errors'
mov rax, 60 ; invoke SYS_exit (kernel opcode 1)
syscall
修改代码后,我再次输入上面的命令:
nasm -f elf64 helloworld.asm -o helloworld.o
ld -o helloworld helloworld.o -m elf_x86_64
./helloworld
好不再有错误。但是也没有输出,应该是“helloworld”
然后我回到前面,首先尝试了教程中给出的命令,从64位模式下工作的源代码构建32位可执行文件:
nasm -f elf helloworld.asm
其结果是:
helloworld.asm:16:错误:在32位模式下不支持指令helloworld.asm:17:错误:32位模式下不支持指令
helloworld.asm:20:错误:32位模式下不支持指令
helloworld.asm:21:错误:32位模式下不支持指令 然后我再次搜索此错误,但找不到解决方案。
我的机器是64位Linux Ubuntu,作为64位Windows 10中Linux的Windows子系统 如何正确运行此helloworld程序?
这是否意味着32位Linux NASM教程/程序无法在64位Linux上运行?
还是64位Windows10?
还是在Linux的Windows子系统中 问题是什么?为什么会出现这么多错误?
我应该如何避免将来出现类似的潜在错误?快速修复
您想编译32位还是64位?
您的程序将工作并显示输出,只需通过rsi更改寄存器ecx即可
; Hello World Program - asmtutor.com
; Compile with: nasm -f elf helloworld.asm
; Link with (64 bit systems require elf_i386 option): ld -m elf_i386 helloworld.o -o helloworld
; Run with: ./helloworld
SECTION .data
msg db 'Hello World!',0Ah
SECTION .text
global _start
_start:
mov edx, 13
mov rsi, msg
mov rdi, 1
mov rax, 1
syscall
mov rdi, 0 ; return 0 status on exit - 'No Errors'
mov rax, 60 ; invoke SYS_EXIT (kernel opcode 1)
syscall
使用nasm和ld编译64位的程序
nasm -f elf64 helloworld.asm -o helloworld.o
ld helloworld.o -o helloworld.elf
写入系统调用使用了错误的寄存器。将
mov ecx,msg
更改为mov rsi,msg
。您无法在WSL(Linux的Windows子系统)上执行32位代码。这就是为什么会出现exec格式错误。您可以执行64位代码,但只能使用64位系统调用(正如您已经注意到的)。汇编并链接到nasm-f elf64 helloworld.asm;ld helloworld.o-o helloworld
你应该可以走了。我已经更改了代码,它工作正常。这是否意味着我需要修改教程中的每个32位nasm?或者可以转换/允许32位代码编译、链接和运行?另外,如果WSL不能执行32位代码,本机Linux可以吗?64位调用约定和系统调用编号与32位不同。显然,指针大小也不同。没有一种简单的方法可以将32位转换为64位。本机linux可以执行32位,除非特别禁用。。永远不要从64b可执行文件调用32b服务。大多数常见的linux安装实际上都会以某种有限的方式(请参阅上面的Q+A了解更多详细信息)(但不是WSL),但是如果您有32b教程,您应该构建32b可执行文件。这在WSL中也是不可能的。我认为目前所有的linux发行版仍然支持32b二进制文件,尽管有些发行版极力反对32b二进制文件。对于类似教程的东西,在虚拟机中安装任何linux都可能足够好(或者可以选择一些较旧的32位ISO)。movesi,msg
也可以,因为您正在制作一个非PIE可执行文件。在默认代码模型中,符号地址保证在低32位的虚拟地址空间中。类似地,movedi,1
/moveax,1
将节省代码大小,如果NASM没有为您进行优化。如果您确实想将一个可能为64位的符号地址放入寄存器,最好的方法是learsi,[rel msg]
。请注意,WSL1类似于没有配置IA32仿真的Linux内核,因此在64位模式下没有int0x80
系统调用,也没有32位ELF可执行文件。因此,“您想编译32位还是64位?”问题的答案应该是“64位”。但实际上最大的建议是:通常在完成教程之前不要尝试移植教程。查找您想要使用的系统的教程,因为asm是高度不可移植的,这一问题充分说明了这一点。(它在做必要的研究以找到64位系统调用信息方面做了很好的尝试,但在将64位代码组装回32位可执行文件等方面做了大量的猜测。学习更多关于x86-64的知识会使这一点不那么令人困惑。)Pete欢迎您的知识,我希望每次我失败时你都能纠正我,但这让我有点难以快速理解你的所有内容,因为它是deep=)。再次感谢你
nasm -f elf64 helloworld.asm -o helloworld.o
ld helloworld.o -o helloworld.elf