我在windows 10上,安装了cygwin,我一直在使用cygwin进行c和汇编程序的编译/汇编,使用cygwin安装的"gcc"和"nasm",据我所知,nasm有一个-f win64模式,所以它可以汇编64位程序,现在,对于windows上的x64汇编编程,YouTube似乎缺少教程,YouTube上的大多数汇编编程教程要么是针对X64 Linux,要么是针对X32 Windows,我需要能够将字符串打印到X64 Windows上的控制台,而不使用任何外部函数,如C语言的"printf"。
StackOverflow链接,没有为我工作:
64-bit windows assembler
据我所知,nasm确实支持使用-f win64扩展名的64位窗口,而且,答案与如何在x64位窗口上用汇编语言编写实际程序无关
How to write hello world in assembler under Windows?
所有给出代码的答案都只给出了过时windows版本(32位)的代码,除了一个。一个适用于64位的答案我试过了,但是链接目标文件的命令给了我一个错误,系统找不到指定的路径。
windows x64 assembler?
这个网站不包含任何代码,这是我所需要的。还有,我正在尝试用nasm写你好世界程序。
64 bit assembly, when to use smaller size registers
这个问题实际上包含了hello world程序的代码,但是当在windows10(我的设备)上的cygwin下执行时,我得到了一个分段错误。
Why does Windows64 use a different calling convention from all other OSes on x86-64?
我曾经尝试过用objdump-d反汇编一个C Hello World程序,但是这调用了printf,一个预构建的C函数,我正在努力避免使用外部函数。
我尝试过其他外部函数(如Messagebox),但它们返回错误,因为有些东西无法识别这些函数。此外,如果可能,我正在尝试不使用任何外部函数,只使用系统调用、系统输入或中断。
代码:
尝试#1:
section .data
msg db "Hello, World!", 10, 0
section .text
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, 14
syscall
mov rax, 60
mov rdi, 0
syscall
问题:正确汇编和链接,但在运行时抛出分段错误。
尝试#2:
section .text
mov ah, 0eh
mov al, '!', 0
mov bh, 0
mov bl, 0
int 10h
问题:组装不当;显示"测试. asm:3:错误:操作码和操作数的组合无效"
尝试3:
section .text
msg db 'test', 10, 0
mov rdi, 1
mov rsi, 1
mov rdx, msg
mov rcx, 5
syscall
mov rdi, 60
mov rsi, 0
syscall
问题:正确汇编和链接,但在运行时抛出分段错误。
尝试#4:
section .text
mov ah, 0eh
mov al, '!'
mov bh, 0
mov bl, 0
int 10h
问题:正确汇编和链接,但在运行时抛出分段错误。
我只需要一个在64位Windows 10上工作的hello world汇编程序的示例。32位程序在我运行时似乎会返回错误。如果不使用外部函数就无法将字符串打印到控制台,那么使用外部函数并在64位Windows 10上工作的程序的示例会很好。
我听说windows中的系统调用的地址和linux中的大不相同。
2条答案
按热度按时间zvms9eto1#
尝试#1:
尝试#2:
Windows内部使用中断或系统调用。但是它们没有正式记录,并且可以随时更改Microsoft想要更改它们:
只有少数
.dll
文件直接使用系统调用指令;所有程序都直接或间接地访问这些.dll
文件。在Windows更新之前,某个序列(例如
mov rax, 5
、syscall
)可能具有"打印文本"的含义,而Microsoft可能在Windows更新之后将此序列的含义更改为"删除文件"。要做到这一点,微软只需替换内核和
.dll
文件,这些文件被正式"允许"使用syscall
指令。调用Windows操作系统函数的唯一方法是调用
.dll
文件中的函数-就像在C程序中执行此操作一样,这样可以保证您的程序在下一次Windows更新后仍然可以工作。示例(32位代码):
ecfsfe2w2#
请看ReactOS源代码。此程序使用NT API将Hello,world!\n打印到控制台。
解释
首先,我们通过从
PEB
访问_RTL_USER_PARAMETERS
来提取StandardOutput
句柄。调用
NtWriteFile
到StandardOutput
调用
NtTerminateProcess
退出。调用约定
syscall
指令清除用于rflags的R11
和用于RIP
的RCX
,因此第一个参数在R10
上。| 系统调用编号|参数0|参数1|精氨酸2|精氨酸3|
| - ------| - ------| - ------| - ------| - ------|
| 拉克斯|R10|黑索今|八国集团|第九代|
关于堆栈参数,由于卷影存储(32字节),它从
40[rsp]
开始,8字节来自call
指令。兼容性
可在NT 6.3(Windows 8.1)及更高版本中运行。NT 6.1(Windows 7)及更旧版本不运行。