简短描述:
在我的第一行设置断点.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
完整的程序在反汇编中可见,但问题仍然存在。尽管我的程序从预期的地址开始,and反汇编中显示第一个断点,但它仍然被跳过。放置一个int 3
因为第一行仍然会产生以下行:
00400FFF add ah,cl
并且不停止执行,and再次在反汇编中重新破坏我的程序的视图。我的程序的下一行位于位置00401001
,我认为这是有道理的,因为int 3
是一条单字节指令,但为什么它会在反汇编中消失呢?
即使使用“Step Into (F11)”命令启动程序也不允许我在第一行中断。事实上,在没有断点的情况下,使用 F11 启动程序根本不会停止执行。
除了我在这里详细介绍的内容之外,我不太确定还能尝试什么来解决该问题。这超出了我目前对汇编和调试器的理解。