第一步都是创建一个简单的汇编语言源文件。创建文件 hw64.asm[Asm] 纯文本查看 复制代码 includelib kernel32.lib
extrn __imp_GetStdHandle:proc ; 导入 GetStdHandle 函数
extrn __imp_WriteFile:proc ; 导入 WriteFile 函数
.CODE
hwStr byte "Hello World!" ; 定义一个字符串 "Hello World!"
hwLen = $-hwStr ; 计算字符串长度
main PROC
; 进入时,栈在 8 mod 16 对齐。为 "bytesWritten" 留出 8 字节,
; 确保 main 中的调用的栈对齐到 16 字节。
lea rbx, hwStr ; 将字符串指针加载到 rbx
sub rsp, 8 ; 为 bytesWritten 留出空间
mov rdi, rsp ; 在这里保存写入的字节数
; 注意:必须为 shadow registers 留出 32 字节 (20h) 的空间
; 参数(只需为所有函数做一次)。此外,WriteFile 有一个
; 第五个参数(为 NULL),因此我们必须留出 8 字节来存放
; 该指针(并初始化为零)。最后,栈必须始终保持 16 字节对齐,
; 所以再保留 8 字节的存储。
; 为参数的 shadow 存储(始终 30h 字节)。
sub rsp, 030h
; 句柄 = GetStdHandle(-11);
; 单个参数传递在 ECX 中。
; 句柄返回在 RAX 中。
mov rcx, -11 ; STD_OUTPUT 的值
call qword ptr __imp_GetStdHandle ; 调用 GetStdHandle
; WriteFile(handle, "Hello World!", 12, &bytesWritten, NULL);
; 将 "LPOverlapped" 参数清零(设置为 NULL):
mov qword ptr [rsp + 4 * 8], 0 ; 第五个参数在栈上
mov r9, rdi ; 将 "bytesWritten" 的地址放到 R9
mov r8d, hwLen ; 将要写入的字符串长度放到 R8D
lea rdx, hwStr ; 将字符串数据的指针放到 RDX
mov rcx, rax ; 文件句柄放到 RCX
call qword ptr __imp_WriteFile ; 调用 WriteFile
add rsp, 38h ; 清理栈空间
ret ; 返回
main ENDP
END
这个汇编源代码使用GPT改成中文注释的,你会看到第一行如下:includelib kernel32.libkernel32.lib是一个 Windows 库,其中包括此汇编语言程序使用的和函数。要编译(汇编)此文件,使用 微软 MSVC编译中 ml64.exe 微软汇编器,输入以下命令:[Shell] 纯文本查看 复制代码 ml64 hw64.asm /link /subsystem:console /entry:main
|