我刚刚开始在win32上学习一些x86程序集,并且我使用masm和visual studio 2008一起使用了.asm文件的ide附带的自定义构建规则。我一直在尝试使用DOS中断打印到控制台,但我收到消息:“ASMTest.exe中0x00401004处的未处理异常:0xC0000005:访问冲突读取位置0xffffffff。”在8号线。我正在尝试输出单个ascii字符'A'(41h)这是masm代码:
.386
.MODEL flat, stdcall
.CODE
start:
mov dl, 41h
mov ah, 2
int 21h
ret
end start
当我使用debug.exe并使用'a'命令输入所有.CODE指令并运行它('g')时,它可以正常工作。
任何人都可以告诉我如何正确使用DOS中断?谢谢!
编辑:在win32上编程时,Managu是正确的,你应该使用像WriteConsoleA这样的Windows api调用,而不是使用DOS中断。 This是一个有用的资源。如果有人正在寻找代码来执行此操作(就像我一样),这里是:
.386
.MODEL flat, stdcall
; Windows API prototypes
GetStdHandle proto :dword
WriteConsoleA proto :dword, :dword, :dword, :dword, :dword
ExitProcess proto :dword
STD_OUTPUT_HANDLE equ -11
.DATA
HelloWorldString db "hello, world", 10, 0
.CODE
strlen proc asciiData:dword
; EAX used as count, EBX as ascii char pointer, EDX (DL) as ascii char
mov eax, -1
mov ebx, asciiData
mov edx, 0
BeginLoop:
inc eax ; ++count (init is -1)
mov dl, [ebx] ; *dl = *asciiptr
inc ebx ; ++asciiptr
cmp dl, 0 ; if (*dl == '\0')
jne BeginLoop ; Goto the beginning of loop
ret
strlen endp
main proc
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov ecx, eax
invoke strlen, addr HelloWorldString
invoke WriteConsoleA, ecx, addr HelloWorldString, eax, 0, 0
ret
main endp
end
(将入口点设置为main)
答案 0 :(得分:3)
当您使用debug.exe输入此代码时,您正在组装一个16位(8086架构,“实模式”)dos程序。您指定的语义对于此类程序是正确的。但是,当您组装MASM中的程序,然后链接它时,您正在尝试创建一个32位(i386架构,“保护模式”)Windows程序。我可能会弄错,但在后一种情况下,我认为你甚至不能合法地调用21h。
答案 1 :(得分:0)
由于你的'ret'指令,它可能会发生。你要回到哪里?我想,在记忆中有一些不为人知的地方。
相反,尝试使用int 20h。那将“优雅地”退出。
它在调试中工作(可能),因为这是一个更“管理”的环境。
答案 2 :(得分:0)
如果我们启动一个16位DOS - * .com应用程序,那么DOS在我们的PSP中填充偏移量为0的“int 20”指令的操作码,而另外的DOS在我们的堆栈上推送一个带有零的字,然后DOS让我们的应用程序执行所以我们可以在代码的末尾放置一个简单的“ret”指令。但是我们必须确保我们的堆栈指针没有被破坏,我们的代码段也没有改变。
为了使用MASM 6+链接16位应用程序,我们需要一个16位链接器。
ftp://ftp.microsoft.com/softlib/mslfiles/lnk563.exe
德克