Visual studio 2010 Visual Studio仅在第二行程序集上中断? 简短描述:
在汇编程序中myVisual studio 2010 Visual Studio仅在第二行程序集上中断? 简短描述:,visual-studio-2010,assembly,masm,Visual Studio 2010,Assembly,Masm,在汇编程序中my.code段的第一行设置断点不会停止程序的执行 问题是: 如果VisualStudio的调试器允许它在汇编程序中编写的程序的第一行创建断点时失败,该怎么办?这是调试器的一些奇怪之处,是多字节指令中断的情况,还是我只是在做一些愚蠢的事情 详情如下: 我在Visual Studio中编译并运行了以下汇编程序: ; Tell MASM to use the Intel 80386 instruction set. .386 ; Flat memory model, and Win 32
.code
段的第一行设置断点不会停止程序的执行
问题是:
如果VisualStudio的调试器允许它在汇编程序中编写的程序的第一行创建断点时失败,该怎么办?这是调试器的一些奇怪之处,是多字节指令中断的情况,还是我只是在做一些愚蠢的事情
详情如下:
我在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
这里有趣的是,在VisualStudio看来,xor
是我程序中的第一个操作。缺少行移动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
并且不会停止执行,并在反汇编中再次损坏程序的视图。然后,我的程序的下一行位于位置00401001
,我认为这是有意义的,因为int 3
是一条单字节指令,但为什么它会在反汇编中消失呢
即使使用“单步执行(F11)”命令启动程序,也不允许我在第一行中断。事实上,如果没有断点,用F11启动程序根本不会停止执行
除了我在这里详述的以外,我不确定我还能尝试解决什么问题。这超出了我目前对汇编和调试器的理解。如果按F+11(单步执行)而不是开始调试,调试器将在第一行停止
可能是断点设置有问题。删除项目目录中的所有*.suo文件以重置所有断点
请注意,如果您的项目有一个main函数,那么它将有一个秘密的标题和内容。要在实际入口点设置断点,请使用:调试+新建断点+函数处中断->windows程序的WWINMINCRTSTARTUP或控制台程序的mainCRTStartup或wmainCRTStartup
01370FFF添加字节ptr[ecx+6],bh
至少我能解释一个谜团。请注意地址0x1370fff。代码段从不从这样的地址开始,而是从0x1000的倍数开始。这使得起始地址的最后3个十六进制数字始终为0。调试器被搞糊涂了,开始在错误的地址逐个分解代码。实际起始地址为0x1371000。由于0x1370fff处有一个0,因此反汇编开始时很糟糕。这是一个多字节加法指令。因此,它会显示垃圾一段时间,直到它意外地赶上了真正的机器代码指令
您需要帮助它,并给它一个命令,以便在正确的地址开始反汇编。在地址框中,键入“0x1371000”
另一个值得注意的怪癖是起始地址的奇怪值。进程通常从地址0x400000开始。启用了一个名为ASLR的功能,地址空间布局随机化。它是一种防病毒功能,可使程序在不可预知的起始地址启动。这是一个不错的特性,但它并不能帮助调试程序。不清楚您是如何构建此代码的,但需要使用/DYNAMICBASE:NO linker选项将其关闭
这里您需要记住的调试器的另一个重要怪癖是它们设置断点的方式。它们通过修补代码,用int3
指令替换指令的起始字节来实现。当断点命中时,它会用原始机器代码指令字节快速替换该字节。所以你从来没见过这个。如果您选择错误的地址来设置断点,那么这就错了,就像在多字节指令的中间。它现在不再中断代码,更改后的字节会弄乱原始指令。当你开始一个糟糕的拆卸时,你很容易陷入这个陷阱
好吧,用正确的方法来做。改用调试器的STEP命令开始调试。我已经发现了问题的根源,但我不知道为什么会这样 在创建另一个MASM项目后,我注意到新的项目将在程序的第一行中断,并且反汇编似乎没有损坏或更改。因此,我将其属性与原始项目(用于调试配置)进行了比较。我发现的唯一区别是我原来的项目禁用了增量链接。具体来说,它向链接器命令行添加了
/INCREMENTAL:NO
从命令行中删除此选项(从而启用增量链接)会导致程序在调试期间按预期运行;反汇编窗口中显示的代码保持不变,我可以在
main
过程的第一行上点击断点,并且int 3
指令也可以作为第一行正确执行。“int 3”和“int 3”是两个不同的指令-尝试后一个指令(它是一个字节)。在Linux中,有时将“nop”作为文件中的第一项是很有帮助的。不同的情况,但在这里可能也有帮助(?。看起来您在不重建的情况下更改了代码:)您是否尝试重建然后设置断点?@FrankKotler感谢您的建议,但是int3
是MASM中的语法错误int 3
绝对是英特尔平台的正确指令。@OhadHoresh该版本是最新的。如果不是,我将无法命中任何断点,因为源将过期
.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
00400FFF add ah,cl