2009-09-12 87 views
3

我刚刚开始在win32上学习一些x86程序集,并且我已经使用ide for .asm文件附带的自定义构建规则在Visual Studio 2008中使用了masm。我一直在尝试使用DOS中断打印到控制台,但是我收到消息:“ASMTest.exe中0x00401004处未处理的异常:0xC0000005:访问冲突读取位置0xffffffff。”在第八行。我试图输出单个ASCII字符“A”(41H)这里是MASM代码:DOS中断masm x86程序集崩溃

.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 

,这是因为你的“RET的(设置的入口点主)

回答

3

当您使用debug.exe输入此代码时,您正在组装一个16位(8086架构,“实模式”)dos程序。您指定的语义对于这样的程序是正确的。但是,当您将MASM中的程序组装到此处时,然后将其链接起来,则会尝试创建一个32位(i386体系结构,“受保护模式”)Windows程序。我可能会误解,但我认为你在后一种情况下甚至可以合法地调用int 21h。

+0

@unknown:你甚至告诉MASM为您创造一个32位可执行文件('.MODEL flat') – 2009-09-12 05:19:32

0

这是可能的'指示。你在哪里回来?我想象的是记忆中一些不为人知的地方。

而是尝试使用int 20h。那将会“优雅地”退出。

它工作在调试(可能),因为这是一个更“管理”的环境。

0

如果我们启动一个16位的DOS - *。com应用程序,那么DOS在我们的PSP内部的偏移量为0处填充“int 20”指令的操作码,并且在DOS之前,额外的DOS在我们的堆栈上推零字我们的程序执行所以我们可以在代码末尾放置一个简单的“ret”指令。但是我们必须确保我们的堆栈指针没有被破坏,并且我们的代码段没有被改变。

对于使用MASM 6+链接16位应用程序,我们需要一个16位链接器。

ftp://ftp.microsoft.com/softlib/mslfiles/lnk563.exe

德克