【发布时间】:2018-10-01 12:59:34
【问题描述】:
我在安装了 Cygwin 的 Windows 10 上。我一直在使用 Cygwin 编译/汇编 c 和使用 Cygwin 安装的“gcc”和“nasm”的汇编程序。据我所知,nasm 有一个 -f win64 模式,所以它可以汇编 64 位程序。现在,对于 windows 上的 x64 汇编编程,youtube 似乎缺少教程。 youtube 上的大多数汇编编程教程都是针对 x64 linux 或 x32 windows 的,我需要能够在 x64 windows 上将字符串打印到控制台,而无需使用任何外部函数,例如 C 的“printf”。
对我不起作用的 StackOverflow 链接:
据我所知,nasm 使用 -f win64 扩展名支持 64 位窗口。此外,答案与如何在 x64 位窗口上用汇编编写实际程序无关
How to write hello world in assembler under Windows?
所有给出代码的答案都只给出过时的 Windows 版本(32 位)的代码,除了一个。我尝试了一个适用于 64 位的答案,但是链接目标文件的命令给我一个错误,系统找不到指定的路径。
这个网站不包含任何代码,这是我需要的。另外,我正在尝试用 nasm 编写 Hello World 程序。
64 bit assembly, when to use smaller size registers
这个问题实际上包含一个 hello world 程序的代码,但是当在 windows 10(我的设备)上的 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
问题:没有正确组装;说“test.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 中的地址大不相同。
【问题讨论】:
-
This MASMForum link 会帮助你。它是获得最佳 MASM64 Windows 源代码的关键。
-
尝试 2 是 16 位 DOS 代码,不能作为 windows 可执行文件运行,
mov al,imm8指令只能包含单个 8 位立即数,所以你必须选择如果你想要数字'!'(@ 987654334@ IIRC ASCII 表)或编号0,不能同时分配给注册al。尝试 3:除非您使用某些标签指定代码开始的位置,否则它可能从.text部分的开头开始,将字符串数据“test”作为指令执行(懒得检查它们形成什么样的指令)。像_start:这样的标签通常与链接器配合使用来指定代码的入口点 -
Attemp 4 又是 16 位 DOS 代码(使用 BIOS 中断
int 10h),因此您可以在某些 DOS 模拟器/VM 下使用这个代码,例如 dosbox。 ..(我猜尝试 1 和 3 正在使用 linux 或 OSX 系统调用,但我不知道 windows 64b 系统调用是如何工作的,所以我什至无法识别正确的方法,我在过去十年中只使用 linux,有时使用 DOS在dosbox中) -
是否有一个特殊的标志可以用 ld 设置来指定程序的开始位置?我尝试将 _start 放在那里并将消息放在 .data 部分中,它仍然显示“非法指令”,所以我假设 ld 仍然不知道从哪里开始。
-
这个问题有点像this。
标签: windows assembly x86-64 system-calls interrupt