我正在做一个项目来学习汇编代码如何集成到编程语言中,以便我可以在处理大型项目时深入理解机器代码抽象。 我使用 VScode 进行编辑,但使用带有开发人员命令行的 MSVC 工具将每个文件编译为 .obj 文件。我的程序集应该打印“选择菜单选项”,然后在执行时打印 4 个菜单项以进行控制台,但目前仅在链接它们后在我的 C 文件中打印测试字符串。
编译main.asm:[ ml /c main.asm ] 编译 procedure.c: [ cl /c procedure.c ]
链接文件: [ link main.obj procedure.obj /OUT:spectra.exe /SUBSYSTEM:CONSOLE /ENTRY:central /LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio�2\BuildTools\VC\Tools \MSVC .42.34433\lib\x86" ucrt.lib libcmtd.lib /NODEFAULTLIB:LIBCMT ]
main.asm:
.model flat, stdcall
EXTERN sayHello: PROC
.data
; Menu strings
menu_msg DB "Select a menu option 1 - 4:$"
.code
central PROC near stdcall
; Print menu options
lea dx, menu_msg ; Load address of menu message
mov ah, 09h ; DOS interrupt for printing strings
int 21h
call sayHello
central ENDP
END
程序.c:
#include <stdio.h>
#include <math.h>
/* Testing & Debugging Functions */
__declspec(dllexport) void sayHello() {
printf("Hello from C!\n");
}
我尝试以 10 种不同的方式链接它们,从指定 /SUBSYSTEM 到 /ENTRY 到指定 MSVC 文件夹中的确切库,它只执行我显式放入 C 文件中的代码,从不运行汇编文件中的任何内容。我该怎么做才能执行汇编代码并将消息打印到控制台?
更新:我试图让 16 位程序集在 64 位 Windows 的终端中运行。我有一些更新的代码,在链接后我终于能够从终端运行,但我无法专门从控制台打印。 C 文件保持不变,但我的程序集已更新,可以打开消息框并显示到目前为止的文本。
编译程序集 = [ ml64 /c /Fo main2.obj main2.asm ] 编译 C 代码 = [ cl /c procedure.c /Fo:procedures.obj ] 链接文件: [ link /OUT:spectra.exe main2.obj procedure.obj /SUBSYSTEM:CONSOLE /ENTRY:main /LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio�2\Community\VC\Tools\ MSVC .42.34433\lib\x64" user32.lib libucrt.lib libvcruntime.lib ]
; main2.asm (for 64-bit)
option casemap:none
EXTERN MessageBoxA: PROC
EXTERN ExitProcess: PROC
EXTERN sayHello: PROC
.data
menu_msg db "Select a menu option:", 0 ; Title of the message box
option1 db "1. Add two numbers", 0
option2 db "2. Subtract two numbers", 0
option3 db "3. Multiply two numbers", 0
option4 db "4. Divide two numbers", 0
; Combine the menu options in the message body
combined_msg db "1. Add two numbers", 0, "2. Subtract two numbers", 0
msg_line2 db "3. Multiply two numbers", 0, "4. Divide two numbers", 0
.code
main PROC
; Align the stack to 16-byte boundary
sub rsp, 8 ; Adjust stack for 16-byte alignment
; Call MessageBoxA with the new title and combined message
mov rcx, 0 ; uType (0 = OK button)
lea rdx, option1 ; lpCaption (title of the message box)
lea r8, menu_msg ; lpText (message with menu options)
mov r9, 0 ; hWnd (no parent window)
call MessageBoxA ; Call MessageBoxA API
; Add another message box with second part if needed
lea r8, msg_line2 ; Update text to the next part
call MessageBoxA ; Call MessageBoxA API again
; Call sayHello procedure (assuming sayHello is implemented in C)
call sayHello
; Exit the program
mov rcx, 0 ; Exit code (0)
call ExitProcess ; Call ExitProcess API
; Clean up the stack
add rsp, 8 ; Restore stack
main ENDP
END
@PeterCordes 解决了:“好吧,那就是你的问题了。编写 64 位代码,不要使用任何 int 指令。int 21h 是 DOS,其他 int 数字大多是 BIOS。int 80h 是 Linux 的 32 位系统 -调用接口,您不想在 64 位代码中使用它,即使在 Linux 上您也不想使用 Windows 没有的系统调用;稳定/记录的系统调用 ABI;而是通过 DLL 进行调用,因此,如果您看到显示 int 或系统调用的示例,那么它们不适用于 x64 Windows(或者它们是关于对 DLL 的系统调用 ABI 进行逆向工程等低级有趣的内容)。使用),寻找不同的教程。”