汇编语言 .code 和 codes segment 的区别?

赤勇玄心行天道 2021-04-01 12:13:21
以下代码执行时会出现内存读写异常:
.386
.model flat, stdcall

codes segment
start: mov eax, 0123H
codes ends

end start

我把codes segment改为.code就能正确执行了:
.386
.model flat, stdcall

.code
_start: mov eax, 0123H

end _start

请问这是为什么呢?
...全文
3214 31 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
汇编语言属于“垂死的艺术”,没有什么好书,罗云彬那本书可能是少有的讲win32汇编的书,不过用汇编写win32/win64程序没啥用,不如用C++或者Delphi写,内嵌汇编也很强大(除了不支持宏之外)。主要是熟悉架构(尤其是指令集),Graphics Programming Black Book这本书可以看一下:https://github.com/jagregory/abrash-black-book/releases,这书也比较老了(有中文版),但是讲到很多汇编编程技巧可以参考

  • 打赏
  • 举报
回复
引用 29 楼 zara 的回复:
刚才在 win10 里试了下,和 win7表现一样。 想起来 Sysinternal组件里的 procexp 程序是可以查看 DEP 状态的,运行了自己的两个模式的程序,发现简易定义模式的是 DEP 状态,而 segment 模式的则是 Disabled 状态,而它们的 DllCharacteristics 都是 0 。 看来真是 DEP 惹出来的祸,只是弯子绕得人头晕啊。
引用 30 楼 早打大打打核战争 的回复:
NX_COMPAT就是(data) non-executable compatible的缩写
再次感谢两位大神的回答!再次请问两位大神是如何学习汇编的呢?有什么推荐新手看的书籍或者视频资料呢?
zara 2021-04-07
  • 打赏
  • 举报
回复
在 win7 x64 里试了下 DEP ,开启了 DEP 除外模式。
原来有个下载软件,NetTransport,运行会触发 DEP,系统给出的是 BEX 错误。把它加到除外列表里,是可以正常打开软件了。
自己写了个 asm,把 .data 的地址压栈,通过 ret 转去,简化模式下,.code 里正常,执行到 .data 里出错。但是,如果用 code segment 定义模式,即便在 .data 里也是可以执行的。
查看了这两个程序各节的属性,NetTransport 有一个节是有 Execute 属性的,程序入口却在下一个没 E 属性的节里,这会出错。简化模式,.code 有 E 属性,.data 没有 E 属性,.code 里执行正常,.data 执行出错。code segment 模式,code 和 .data 节都没有 E 属性,没有一个节有 E 属性,结果是两个节都可以执行,甚至转去了堆栈里也能执行。
楼主传过来的第一个程序,有 4 个节,都是没有 E 属性的,所以在 DllCharacterics 域置 0 后也是可以执行。
这样看来,似乎没有 E 属性,就被认为都有 E 属性了,甚至关闭了 DEP 就如其在白名单里。

所以,我还是觉得,楼主这个问题应该和 DEP 无关。
  • 打赏
  • 举报
回复
那是因为你把IMAGE_DLLCHARACTERISTICS_NX_COMPAT标志清除了,参考: https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header32
  • 打赏
  • 举报
回复
引用 23 楼 zara 的回复:
不是这样的吧,否则无法解释什么也不动,只把 DllCharacteristics 置 0 就可以正常运行。
请问这个DllCharacteristics什么意思?
  • 打赏
  • 举报
回复
NX_COMPAT就是(data) non-executable compatible的缩写
zara 2021-04-07
  • 打赏
  • 举报
回复
刚才在 win10 里试了下,和 win7表现一样。
想起来 Sysinternal组件里的 procexp 程序是可以查看 DEP 状态的,运行了自己的两个模式的程序,发现简易定义模式的是 DEP 状态,而 segment 模式的则是 Disabled 状态,而它们的 DllCharacteristics 都是 0 。
看来真是 DEP 惹出来的祸,只是弯子绕得人头晕啊。
  • 打赏
  • 举报
回复
引用 27 楼 zara 的回复:
IMAGE_DLLCHARACTERISTICS_NX_COMPAT,看了 http://www.zyiz.net/tech/detail-129173.html 的介绍,这个是进程 DEP 控制的,除外模式下,进程可以自己调用相应 API 解除 DEP。
楼主的程序是置该标记位的;我的那些个程序包括 NetTransport 都是 0,自己的代码里当然也没有去操作 DEP,但还是出现了不同的 DEP 表现。这个,难道是 win7 这方面不成熟?


系统通过IMAGE_DLLCHARACTERISTICS_NX_COMPAT标志检查pe映像是否DEP兼容,你把这个标志清了,所以对这个程序不启用DEP。
你可以用IDA反汇编一下楼主的两个程序,看一下差别在哪里
zara 2021-04-07
  • 打赏
  • 举报
回复
IMAGE_DLLCHARACTERISTICS_NX_COMPAT,看了 http://www.zyiz.net/tech/detail-129173.html 的介绍,这个是进程 DEP 控制的,除外模式下,进程可以自己调用相应 API 解除 DEP。
楼主的程序是置该标记位的;我的那些个程序包括 NetTransport 都是 0,自己的代码里当然也没有去操作 DEP,但还是出现了不同的 DEP 表现。这个,难道是 win7 这方面不成熟?
zara 2021-04-06
  • 打赏
  • 举报
回复
不是这样的吧,否则无法解释什么也不动,只把 DllCharacteristics 置 0 就可以正常运行。
  • 打赏
  • 举报
回复
引用 21 楼 早打大打打核战争 的回复:
我用vs2015里带的ml 12.00.21005.1测试了一下楼主的程序,确实存在这个问题,第一个会导致AV,第二个则正常执行。之前我认为导致异常的是mov eax, 0123h后面的00 00,实际不是,确实是mov eax, 0123h这条指令的位置出现异常。 继续研究了一下,又用非微软汇编器tasm32、jwasm测试,终于发现了问题之所在。这应该是微软masm隐藏很深的一个BUG。在masm的标准段模型下,同类别名的段会被合并。而你的程序没有显式定义数据段,它会建立一个默认数据段,之后由于BUG,它认为这个两个段可以合并。所以最终pe文件中生成的代码和数据section是地址重合的。而从xp开始,默认启用DEP,数据section禁止执行,所以第一条指令mov eax, 0123h就异常了。 而在简化段模型下(最初是Borland Turbo Assembler创造的,称之为IDEAL模型),.code和.data不会合并,所以对应在pe中是两个不重合的section,于是没有数据执行的问题。 经测试,tasm32、jwasm生成的程序没有这个bug,对于ml,只要给codes段一个别名: codes segment public 'code' 也可以避开这个bug
非常非常感谢大神的精心回答!这个绝对是完美答案! 最后再问下大神,新手学习汇编看什么书或者视频比较好?
  • 打赏
  • 举报
回复
我用vs2015里带的ml 12.00.21005.1测试了一下楼主的程序,确实存在这个问题,第一个会导致AV,第二个则正常执行。之前我认为导致异常的是mov eax, 0123h后面的00 00,实际不是,确实是mov eax, 0123h这条指令的位置出现异常。
继续研究了一下,又用非微软汇编器tasm32、jwasm测试,终于发现了问题之所在。这应该是微软masm隐藏很深的一个BUG。在masm的标准段模型下,同类别名的段会被合并。而你的程序没有显式定义数据段,它会建立一个默认数据段,之后由于BUG,它认为这个两个段可以合并。所以最终pe文件中生成的代码和数据section是地址重合的。而从xp开始,默认启用DEP,数据section禁止执行,所以第一条指令mov eax, 0123h就异常了。
而在简化段模型下(最初是Borland Turbo Assembler创造的,称之为IDEAL模型),.code和.data不会合并,所以对应在pe中是两个不重合的section,于是没有数据执行的问题。
经测试,tasm32、jwasm生成的程序没有这个bug,对于ml,只要给codes段一个别名:
codes segment public 'code'
也可以避开这个bug
  • 打赏
  • 举报
回复
引用 19 楼 zara 的回复:
又对比了下我的和楼主的两个 exe,发现 pe 头部的 DllCharacteristics 域有不同,该值资料上说总是 0000,楼主的程序1 是 8540,程序2 是 8140 。从表现来看,代码节正常属性时,似无甚影响;若有异,就必须是 0000 了。再具体的是怎么发神经的,资料和水平有限,无力深究了。
引用 18 楼 zara 的回复:
[quote=引用 14 楼 赤勇玄心行天道 的回复:]上传了: https://download.csdn.net/download/cyz7758520/16436554
抱歉啊,具体真实的原因没能看出来。测试对比了下,如果将 code 节有 C0000040(R/W/I) 改为 60000020(R/E/C) 就可以运行的;但拿最上面的简单代码用 msam32v8 生成的 exe 也是 C0000040 却是可以的,只是这个 exe 较之楼主的少了其它的节如 rdata rsrc 和 reloc 等,但似乎节间不应该有纠缠吧?另外,如果直接运行不用调试,提示是程序开始处访问自身出错,那里不可写,其实用 vmmap 程序查看,却是 RW 属性,调试软件也确实是开诶修改那里的指令;所以,感觉问题其实应该不在这里,觉得应该在更早的阶段即系统的模块加载部分。[/quote] 非常感谢大神的帮助!小弟再继续研究一下。
zara 2021-04-05
  • 打赏
  • 举报
回复
又对比了下我的和楼主的两个 exe,发现 pe 头部的 DllCharacteristics 域有不同,该值资料上说总是 0000,楼主的程序1 是 8540,程序2 是 8140 。从表现来看,代码节正常属性时,似无甚影响;若有异,就必须是 0000 了。再具体的是怎么发神经的,资料和水平有限,无力深究了。
zara 2021-04-05
  • 打赏
  • 举报
回复
引用 14 楼 赤勇玄心行天道 的回复:
上传了:
https://download.csdn.net/download/cyz7758520/16436554

抱歉啊,具体真实的原因没能看出来。测试对比了下,如果将 code 节有 C0000040(R/W/I) 改为 60000020(R/E/C) 就可以运行的;但拿最上面的简单代码用 msam32v8 生成的 exe 也是 C0000040 却是可以的,只是这个 exe 较之楼主的少了其它的节如 rdata rsrc 和 reloc 等,但似乎节间不应该有纠缠吧?另外,如果直接运行不用调试,提示是程序开始处访问自身出错,那里不可写,其实用 vmmap 程序查看,却是 RW 属性,调试软件也确实是开诶修改那里的指令;所以,感觉问题其实应该不在这里,觉得应该在更早的阶段即系统的模块加载部分。
luj_1768 2021-04-05
  • 打赏
  • 举报
回复
写的太规范,别人也只好规范对待;随便一些,大家通融通融就好。
  • 打赏
  • 举报
回复
引用 13 楼 赤勇玄心行天道 的回复:
[quote=引用 10 楼 早打大打打核战争 的回复:]因为x86/x64的异常有三类:faults, traps, aborts
windows错误代码0xc0000005(Access Violation)对应处理器异常13(General Protection Fault),属于fault型异常,在指令前边界检测处理,而int n、into、单步之类的异常属于trap型异常,在指令后边界检测处理


大神,能说明白点吗?什么叫边界检测处理?我这第一个程序异常的原因是什么?为什么第二个没有访问冲突?[/quote]

简单说,fault型异常在修改指令指针之前触发,trap型异常在修改指令指针之后触发
liuchen20100902 2021-04-04
  • 打赏
  • 举报
回复
看看是啥亚!!!!
  • 打赏
  • 举报
回复
引用 11 楼 zara 的回复:
那个指令本身不应该有 5 拒绝访问的,发生这个,单步时的堆栈操作上有问题,还是代码所在节不是可执行的,这个好像怎么都不应该的,exe 文件上传来看看?
上传了: https://download.csdn.net/download/cyz7758520/16436554
  • 打赏
  • 举报
回复
引用 10 楼 早打大打打核战争 的回复:
因为x86/x64的异常有三类:faults, traps, aborts windows错误代码0xc0000005(Access Violation)对应处理器异常13(General Protection Fault),属于fault型异常,在指令前边界检测处理,而int n、into、单步之类的异常属于trap型异常,在指令后边界检测处理
大神,能说明白点吗?什么叫边界检测处理?我这第一个程序异常的原因是什么?为什么第二个没有访问冲突?
加载更多回复(11)

21,497

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧