Winapi “一个如何显示?”;你好,世界&引用;不使用高级汇编程序的好处?

Winapi “一个如何显示?”;你好,世界&引用;不使用高级汇编程序的好处?,winapi,assembly,x86,x86-64,Winapi,Assembly,X86,X86 64,我试图在64位Windows7机器上用FASM显示“Hello,world!”,而不使用现代汇编程序所提供的拐杖 这个相当简单的任务令人惊讶地沮丧,因为我能找到的每个示例和教程都坚持使用宏,包括预先编写的代码,或者从高级语言导入库。我认为想学习组装的人通常是为了对计算机的工作原理有一个直接而亲密的了解。所有这些抽象和混淆似乎都有损于这一目的 除此之外,我正在寻找可以在控制台上显示“Hello,world!”的代码,而无需重用、包括和导入任何内容,只需直接访问Windows API即可。虽然我知道

我试图在64位Windows7机器上用FASM显示“Hello,world!”,而不使用现代汇编程序所提供的拐杖

这个相当简单的任务令人惊讶地沮丧,因为我能找到的每个示例和教程都坚持使用宏,包括预先编写的代码,或者从高级语言导入库。我认为想学习组装的人通常是为了对计算机的工作原理有一个直接而亲密的了解。所有这些抽象和混淆似乎都有损于这一目的

除此之外,我正在寻找可以在控制台上显示“Hello,world!”的代码,而无需重用、包括和导入任何内容,只需直接访问Windows API即可。虽然我知道许多汇编程序都附带了提供对Windows API访问的文件,但我不希望依赖它们

另外,如果您对我可以使用哪些汇编程序或教程来更好地促进我的学习方法有任何建议,我将不胜感激

  • 向谷歌寻求帮助:
  • 试着自己做


  • 用于编译以下hello world(16位)代码:

    “纯”windows编程的一个大问题是windows要求程序包含导入部分,即系统DLL中的哪些函数必须提供给程序,即所谓的导入表

    此表不是程序的一部分,与汇编程序本身无关。此外,导入表结构复杂,手工构建不太方便。这就是为什么FASM为用户提供了一些标准的方法来构建这些导入表

    如果您的目标是学习汇编,那么正确的方法是阅读FASM手册(其中描述了这些宏),然后阅读任何FASM发行版中提供的示例代码,然后开始使用它们并集中精力进行汇编编程

    适度使用宏不会减少程序的汇编编写


    这里是提问和寻求帮助的好地方,但毕竟你必须做好功课。

    在windows下运行的每个进程都会将kernel32或KernelBase加载到其地址空间,利用这一事实和PEB内部结构,你可以轻松访问任何windows功能(只要你有正确的访问权限)

    博客条目详细介绍了如何使用
    MessageBoxA
    显示消息


    老实说,除非你有什么极端的理由这样做,否则你只会浪费时间,而不是使用提供的工具(在本例中,是一个链接器,这样你就可以访问任何windows API,而不必经历10000个障碍和循环)。

    我只链接到一个库(
    kernel32.dll
    )并参考3个功能:

    GetStdHandle
    
    WriteConsole
    
    ExitProcess
    
    下面的代码是我详尽的谷歌搜索的结果,以及我自己对微软文档的引用

    format PE console
    entry start
    
    include 'include\win32a.inc'
    
    section '.data' data readable writable
         msg     db 'Hello World!',13,10,0
         len = $-msg
         dummy   dd ?
    
    section '.code' readable writable executable
    
      start:
    
    push STD_OUTPUT_HANDLE
    call [GetStdHandle] ;STD_OUTPUT_HANDLE (DWORD)-11
    
    push 0      ;LPVOID  lpReserved
    push dummy  ;LPDWORD lpNumberOfCharsWritten
    push len    ;DWORD   nNumberOfCharsToWrite
    push msg    ;VOID    *lpBuffer;
    push eax    ;HANDLE  hConsoleOutput
    call [WriteConsole]
    
    push 0
    call [ExitProcess]
    
    section '.idata' data import readable writable
    
    library kernel32,'KERNEL32.DLL' 
    include 'include\api\kernel32.inc'
    

    我已经看到了。虽然我很感谢您的回复,但我希望在控制台上显示“Hello,world!”,我听说这比在窗口中显示要复杂得多。谢谢,但这段代码是用于DOS的。同一页上有一个Windows示例,但它说要使用
    include win32.inc
    ,这正是我试图避免的。这个答案的x86-64部分显示了如何手动导入WinAPI函数。DOS部分与Windows完全无关。Windows等价物将直接使用x86-64
    syscall
    ,用于某些版本的Windows(未记录且不受支持,并且呼叫号码可以在Windows版本之间更改,这与Linux上直接系统调用ABI稳定的情况不同。)。Windows中的系统调用ID在不同版本的Windows中有所不同。我不认为这有什么意义,但事情就是这样。这就是为什么您希望导入一些系统DLL,其中包含这些系统调用ID,并使用这些DLL中的包装函数来完成工作。我不认为逆向工程那些DLL和操作系统内核会为你节省时间。只需使用DLL。@johnmclane为什么不使用控制台功能,如
    WriteConsole
    ?这是一个C示例:
    GetStdHandle
    
    WriteConsole
    
    ExitProcess
    
    format PE console
    entry start
    
    include 'include\win32a.inc'
    
    section '.data' data readable writable
         msg     db 'Hello World!',13,10,0
         len = $-msg
         dummy   dd ?
    
    section '.code' readable writable executable
    
      start:
    
    push STD_OUTPUT_HANDLE
    call [GetStdHandle] ;STD_OUTPUT_HANDLE (DWORD)-11
    
    push 0      ;LPVOID  lpReserved
    push dummy  ;LPDWORD lpNumberOfCharsWritten
    push len    ;DWORD   nNumberOfCharsToWrite
    push msg    ;VOID    *lpBuffer;
    push eax    ;HANDLE  hConsoleOutput
    call [WriteConsole]
    
    push 0
    call [ExitProcess]
    
    section '.idata' data import readable writable
    
    library kernel32,'KERNEL32.DLL' 
    include 'include\api\kernel32.inc'