【问题标题】:assembly code on Windows 8 x64Windows 8 x64 上的汇编代码
【发布时间】:2013-10-21 04:44:00
【问题描述】:

我是使用汇编代码编程的硬件新手。所以我读了一本关于它的书,发现了这个 NASM 汇编器的示例代码:

segment .text                               ;code segment
global main                                 ;must be declared for linker
main:                                       ;tell linker entry point
mov edx,len                                 ;message length
mov ecx,msg                                 ;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

segment .data                               ;data segment
msg db 'Hello, world!',0xa                  ;our dear string
len equ $ - msg                             ;length of our dear string

所以我用以下命令编译它:

nasm -f elf64 helloworld.asm
ld -s -o helloworld.exe helloworld.o

汇编程序没有问题,可以汇编它并且没有错误,但是程序立即崩溃。我读到了不同的汇编语言,但重点是汇编代码会随着不同的编译器而不是不同的操作系统而变化,那么我的错误在哪里?

【问题讨论】:

  • 你为什么认为问题出在操作系统上。如果运行 Windows 7,它可能会在同一台机器上崩溃。你测试过那个场景吗?如果不是操作系统,那就离开机器。
  • 对于任何 x64 操作系统,我都会先尝试mov rcx, msg(我也怀疑 Win 8 使用 linux 风格的系统调用。Windows 7 没有。)
  • 在 Windows 上,您从 system32.dll 调用 ExitProcess 以退出。系统调用非常特定于操作系统。
  • 您正在尝试在 Windows 中执行 Linux 系统调用,但这是行不通的。请改用 WriteConsoleExitProcess 等 WinAPI 函数。

标签: windows assembly x86-64 nasm


【解决方案1】:

您显示的代码是 x86_32 linux 代码。
你可以看出来,因为它使用了int 调用,而 Windows 不使用这一行:

nasm -f elf64 helloworld.asm

ELF 格式生成输出,这是一个 linux 可执行文件。
Windows 使用 PE (可移植的可执行文件),它是 COFF 的 MS EEE 变体。

x64 代码使用 RAXRBX ....,尽管 32 位变量寄存器 EAX 等也有很多功能。

在您可以学习如何编写汇编之前。
您需要了解系统的 ABI(调用约定)和 API。

对于 ABI,请查看:Calling Conventions - PDF

如果您想知道如何在 Windows 中进行 API 调用,请编写一个简单的 C 程序来完成这项工作,然后获取一个反汇编程序并查看 x86 代码。
有关 API 调用的更多信息,请查看 MSDN,特别是:

Overview of x64 Calling Conventions
Windows Console functions
ExitProcess function

【讨论】:

    【解决方案2】:

    以 PE 格式组装您的可执行文件并将int 0x80 更改为call ExecuteInterrupt128。 你可以给它一个相同的名字。您可以学习如何在 NASM 上编写 PE 可执行文件。 直接去 Stack Overflow 的首页就行了。

    ExecuteInterrupt128 函数必须如下所示:

    push ebp
    mov ebp, esp
    cmp eax, byte +1
    je SleepSystem
    cmp eax, byte +4
    je PrintString
    ...
    SleepSystem:
    push byte -1
    call Sleep
    leave
    ret
    PrintString:
    push -11
    call GetStdHandle
    push byte +0
    push byte +6
    lea esi, [ebp-4]
    push edx
    push ecx
    push eax
    call WriteConsoleA
    leave
    ret
    

    或者试试这个命令:

        nasm -f win32 -o executable.o executable.asm
        ld -o executable.exe executable.o
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      相关资源
      最近更新 更多