首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Visual只会中断第二行的组装?

Visual只会中断第二行的组装?
EN

Stack Overflow用户
提问于 2012-10-26 02:45:14
回答 3查看 850关注 0票数 5

简短的描述:

在程序集中的.CODE段的第一行上设置断点不会停止程序的执行。

问题是:

如果Visual的调试器允许它在以程序集中编写的程序的第一行创建断点,那么怎么办?这是调试器的奇怪之处,是多字节指令中断的情况,还是我只是在做傻事呢?

详情如下:

我在Visual中编译和运行了以下汇编程序:

代码语言:javascript
运行
复制
; 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

如果我试图在主函数的第一行mov ecx, 6上设置一个断点,它就会被忽略,程序就会执行而不停止。只有当我将断点设置在之后的行、xor eax, eax或任何后续行时,才会命中断点。

我甚至尝试插入一个软件断点int 3作为函数的第一行,它也被忽略了。

我注意到的第一件事很奇怪:在碰到一个断点后查看反汇编会给我以下信息:

代码语言:javascript
运行
复制
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  

有趣的是,在Visual看来,xor是我程序中的第一个操作。缺席的是行move ecx, 6。在它认为我的源代码开始的直接上方是实际上将ecx设置为6的行。因此,根据反汇编,我的程序的实际启动已经损坏。

如果我做了程序int 3的第一行,在反汇编中我的代码出现在上面的一行是:

代码语言:javascript
运行
复制
00F80FFF  add         ah,cl

正如其中一个答案所建议的,我关闭了ASLR,看起来反汇编更稳定一些:

代码语言:javascript
运行
复制
.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  

完整的程序在拆卸过程中是可见的,但问题仍然存在。尽管我的程序从预期的地址开始,(反汇编中显示的第一个断点)仍然被跳过。将int 3作为第一行仍然会产生以下行:

代码语言:javascript
运行
复制
00400FFF  add         ah,cl  

并且不会停止执行,并在反汇编中重新破坏我的程序的视图。我的程序的下一行是在location 00401001,我认为这是有意义的,因为int 3是一个单字节的指令,但是为什么它会在反汇编中消失呢?

即使使用'Step (F11)‘命令启动程序,也不允许我中断第一行。事实上,在没有断点的情况下,使用F11启动程序根本不会停止执行。

我不太确定我还能做些什么来解决这个问题,除了我在这里所详述的以外。这超出了我目前对程序集和调试器的理解。

EN

Stack Overflow用户

发布于 2012-11-01 21:12:12

01370FFF添加字节ptr ecx+6,bh

至少我能解释一个谜团。注意地址,0x1370fff。代码段从不从这样的地址开始,段以0x1000的倍数开始。这使得开始地址的最后三个十六进制数字总是0。调试器被弄糊涂了,开始在错误的地址上解压代码,只有一个地址。实际开始地址是0x1371000。因为在0x1370fff处有0,所以反汇编开始得很糟糕。这是一个多字节的添加指令。因此,它会显示垃圾一段时间,直到意外地赶上真正的机器代码指令。

您需要帮助它,并给它一个命令开始分解在适当的地址。在VS中,输入"0x1371000“。

另一个值得注意的怪癖是起始地址的奇怪价值。进程通常从地址0x400000开始。您有一个名为ASLR的功能打开,地址空间布局随机化。这是一个反病毒功能,使程序从一个不可预测的开始地址开始.不错的功能,但它并不完全帮助调试程序。还不清楚是如何构建这段代码的,但是需要/DYNAMICBASE:NO链接器选项来关闭它。

您需要记住的另一个重要的调试器怪癖是它们设置断点的方式。这样做的方法是修补代码,用int 3指令替换指令的起始字节。当断点命中时,它会迅速将字节替换为原始机器代码指令字节。所以你从来没见过这个。如果您选择了错误的地址来设置断点,就会出错,就像在多字节指令的中间。它现在不再破坏代码,修改后的字节会扰乱原始指令。当你开始做一个糟糕的拆卸时,你很容易就会掉进这个陷阱。

好吧,这样做是对的。使用调试器的STEP命令开始调试。

票数 3
EN
查看全部 3 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13080069

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档