我正试图展示“Hello,world!”在64位Windows 7机器上使用FASM,而不使用现代装配商似乎提供的拐杖。
这个相当简单的任务被证明令人惊讶地令人沮丧,因为我能找到的每个示例和教程都坚持使用宏,包括预先编写的代码,或从高级语言导入库。我认为那种想要学习装配的人通常会这样做,以便对计算机的工作原理有直接和深入的了解。所有这些抽象和混淆似乎都有损于此目的。
抛开一边,我正在寻找可以显示“Hello,world!”的代码。在控制台上没有重用,包括和导入除直接访问Windows API之外的任何内容。虽然我知道很多汇编程序都附带了提供Windows API访问权限的文件,但我宁愿不依赖它们。
另外,如果您对我可以使用哪些汇编程序或教程更好地促进我的学习方法有任何建议,我将非常感激。
答案 0 :(得分:2)
“纯”Windows编程的一个大问题是Windows要求程序包含导入部分,关于必须向系统提供系统DLL的哪些功能 - 所谓的导入表。
此表不是程序的一部分,与程序集编程本身无关。此外,导入表结构复杂,手动构建不方便。这就是为什么FASM为用户提供了一些构建这些导入表的标准方法。
如果您的目标是学习装配,那么正确的方法是阅读FASM手册,其中描述了这些宏,然后阅读任何FASM发行版中提供的示例代码,然后开始使用它们并集中精力汇编程序。
适度使用宏不会使您的程序编写更少的汇编!
FASM message board是提问和寻求帮助的好地方,但毕竟你必须完成作业。
答案 1 :(得分:1)
windows下的每个正在运行的进程都会将kernel32或kernalbase加载到其地址空间中,使用此事实和PEB内部,您可以轻松访问任何Windows功能(前提是您具有正确的访问权限)。
This博客条目详细说明如何执行此操作以显示MessageBoxA
的邮件。
说实话,除非你有一些极端的理由这样做,否则你最终会浪费时间,而是使用提供的工具(在这种情况下,是一个链接器,所以你可以访问任何Windows API而无需经过10000障碍和循环)。
答案 2 :(得分:1)
我设法仅链接到一个库(kernel32.dll
)并引用了3个函数:
GetStdHandle
WriteConsole
ExitProcess
下面的代码是我详尽的Google搜索的结果,也是我对MS文档的引用。
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'
答案 3 :(得分:0)
; Example of 64-bit PE program
format PE64 GUI
entry start
section '.text' code readable executable
start:
sub rsp,8*5 ; reserve stack for API use and make stack dqword aligned
mov r9d,0
lea r8,[_caption]
lea rdx,[_message]
mov rcx,0
call [MessageBoxA]
mov ecx,eax
call [ExitProcess]
section '.data' data readable writeable
_caption db 'Win64 assembly program',0
_message db 'Hello World!',0
section '.idata' import data readable writeable
dd 0,0,0,RVA kernel_name,RVA kernel_table
dd 0,0,0,RVA user_name,RVA user_table
dd 0,0,0,0,0
kernel_table:
ExitProcess dq RVA _ExitProcess
dq 0
user_table:
MessageBoxA dq RVA _MessageBoxA
dq 0
kernel_name db 'KERNEL32.DLL',0
user_name db 'USER32.DLL',0
_ExitProcess dw 0
db 'ExitProcess',0
_MessageBoxA dw 0
db 'MessageBoxA',0
使用nasm并从惊人的wiki one page编译这个hello world(16位):
.model tiny
.code
org 100h
main proc
mov ah,9 ; Display String Service
mov dx,offset hello_message ; Offset of message (Segment DS is the right segment in .COM files)
int 21h ; call DOS int 21h service to display message at ptr ds:dx
retn ; returns to address 0000 off the stack
; which points to bytes which make int 20h (exit program)
hello_message db 'Hello, world!$'
main endp
end main