简短说明:
在汇编程序中我的段的第一行设置断点.CODE
不会停止程序的执行。
问题:
如果 Visual Studio 的调试器无法在以汇编语言编写的程序的第一行创建断点,该怎么办?这是调试器的一些奇怪之处,多字节指令中断的情况,还是我只是在做一些愚蠢的事情?
细节:
我在 Visual Studio 中编译和运行了以下汇编程序:
; Tell MASM to use the Intel 80386 instruction set.
.386
; Flat memory model, and Win 32 calling convention
.MODEL FLAT, STDCALL
; Treat labels as case-sensitive (required for windows.inc)
OPTION CaseMap:None
include windows.inc
include masm32.inc
include user32.inc
include kernel32.inc
include macros.asm
includelib masm32.lib
includelib user32.lib
includelib kernel32.lib
.DATA
BadText db "Error...", 0
GoodText db "Excellent!", 0
.CODE
main PROC
;int 3 ; <-- If uncommented, this will not break.
mov ecx, 6 ; <-- Breakpoint here will not hit.
xor eax, eax ; <-- Breakpoint here will.
_label: add eax, ecx
dec ecx
jnz _label
cmp eax, 21
jz _good
_bad: invoke StdOut, addr BadText
jmp _quit
_good: invoke StdOut, addr GoodText
_quit: invoke ExitProcess, 0
main ENDP
END main
如果我尝试在 main 函数的第一行设置断点mov ecx, 6
,它会被忽略,并且程序会在不停止的情况下执行。如果我将断点设置在之后的行xor eax, eax
,或任何后续行上,才会命中断点。
我什至尝试插入一个软件断点,int 3
作为函数的第一行,它也被忽略了。
我注意到的第一件事很奇怪:在遇到我的一个断点后查看反汇编给了我以下信息:
01370FFF add byte ptr [ecx+6],bh
--- [Path]\main.asm
xor eax, eax
00841005 xor eax,eax --- <-- Breakpoint is hit here
_label: add eax, ecx
00841007 add eax,ecx
dec ecx
00841009 dec ecx
jnz _label
0084100A jne _label (841007h)
cmp eax, 21
0084100C cmp eax,15h
这里有趣的xor
是,在 Visual Studio 看来,这是我程序中的第一个操作。缺席的是行move ecx, 6
。它认为我的源代码开始的正上方是实际设置ecx
为 6 的行。因此,我的程序的实际启动已根据反汇编进行了破坏。
如果我制作程序的第一行,int 3
那么反汇编中代码所在的上方显示的行是:
00F80FFF add ah,cl
正如其中一个答案所建议的,我关闭了 ASLR,看起来反汇编更稳定了一些:
.CODE
main PROC
;mov ecx, 6
xor eax, eax
00401000 xor eax,eax --- <-- Breakpoint is present here, but not hit.
_label: add eax, ecx
00401002 add eax,ecx --- <-- Breakpoint here is hit.
dec ecx
00401004 dec ecx
在反汇编中可以看到完整的程序,但问题仍然存在。尽管我的程序从预期的地址开始,并且在反汇编中显示了第一个断点,但它仍然被跳过。将 anint 3
作为第一行仍然会导致以下行:
00400FFF add ah,cl
并且不会停止执行,并再次在反汇编中重新破坏我的程序的视图。然后我的程序的下一行位于 location 00401001
,我认为这是有道理的,因为int 3
它是一个单字节指令,但为什么它会在反汇编中消失?
即使使用“Step Into (F11)”命令启动程序也不允许我在第一行中断。事实上,在没有断点的情况下,使用 F11 启动程序根本不会停止执行。
除了我在这里详细介绍的内容之外,我真的不确定我还能尝试什么来解决这个问题。这超出了我目前对汇编和调试器的理解。